排序算法的分类:
- 内部排序:整个排序过程在内存储器中进行。
- 外部排序:由于待排序元素数量太大,以至于内存储器无法容纳全部数据,排序需要借助外部存储设备才能完成。
直接插入排序与希尔排序效率:
类别 | 排序方法 | 时间复杂度 | 空间复杂度 | 排序方式 | 稳定性 | ||
平均时间复杂度 | 最好情况 | 最坏情况 | |||||
插入排序 | 直接插入排序 | In-place | 稳定 | ||||
希尔排序 | In-place | 不稳定 |
接口:
package com.my.sort;
public interface IArraySort {
public int[] sort(int[] sourceArray);
}
1. 直接插入排序
1.1 算法步骤
- 将第一待排序序列第一个元素看做一个有序序列,把第二个元素到最后一个元素当成是未排序序列。
- 从头到尾依次扫描未排序序列,将扫描到的每个元素插入有序序列的适当位置。(如果待插入的元素与有序序列中的某个元素相等,则将待插入元素插入到相等元素的后面。)
1.2 代码
package com.my.sort;
import java.util.Arrays;
public class Client {
public static void main(String[] args) {
int[] sourceArray = {7,2,6,5,9,4};
InsertSort iSort = new InsertSort();
System.out.println(Arrays.toString(sourceArray));
int[] arr = iSort.sort(sourceArray);
System.out.println(Arrays.toString(arr));
}
}
package com.my.sort;
import java.util.Arrays;
public class InsertSort implements IArraySort {
@Override
public int[] sort(int[] sourceArray) {
//对arr进行拷贝,不改变参数内容
int[] arr = Arrays.copyOf(sourceArray,sourceArray.length);
//从下标为1的元素开始选择合适的位置插入,因为下标为0的只有一个元素,默认是有序的
for(int i = 1; i < arr.length; i++) {
//记录要插入的元素
int temp = arr[i];
//记录要插入元素的下标
int j = i;
//将要插入元素从后向前与已排序的序列的元素进行比较,若已排序元素大于要插入元素,则向后移动一位,最终找到要插入的位置的下标j
while(j > 0 && temp < arr[j - 1]) {
arr[j] = arr[j - 1];
j--;
}
//如果要插入位置的下标不等于要插入元素的原始下标,则插入要插入的元素
if(j != i) {
arr[j] = temp;
}
}
return arr;
}
}
1.3 执行结果
[7, 2, 6, 5, 9, 4]
[2, 4, 5, 6, 7, 9]
2. 希尔排序
2.1 算法步骤
- 选择一个增量序列 t1,t2,……,tk,其中 ti > tj, tk = 1;
- 按增量序列个数 k,对序列进行 k 趟排序;
- 每趟排序,根据对应的增量 ti,将待排序列分割成若干长度为 m 的子序列,分别对各子表进行直接插入排序。仅增量因子为 1 时,整个序列作为一个表来处理,表长度即为整个序列的长度。
2.2 举例说明
要排序数组:int[] arr = {7, 2, 6, 5, 9, 4};
已排序后的数组为:[2, 4, 5, 6, 7, 9]
2.3 代码
package com.my.sort;
import java.util.Arrays;
public class Client {
public static void main(String[] args) {
int[] sourceArray = {7,2,6,5,9,4};
ShellSort sSort = new ShellSort();
System.out.println(Arrays.toString(sourceArray));
int[] arr = sSort.sort(sourceArray);
System.out.println(Arrays.toString(arr));
}
}
package com.my.sort;
import java.util.Arrays;
public class ShellSort implements IArraySort {
@Override
public int[] sort(int[] sourceArray) {
//对arr进行拷贝,不改变参数内容
int[] arr = Arrays.copyOf(sourceArray, sourceArray.length);
//设置最开始的增量(间隔gap)为1
int gap = 1;
while(gap < arr.length) {
gap = gap * 2 + 1;
}
while(gap > 0) {
//将待排序列按照增量进行分组
gap = (int)Math.floor(gap / 2);
for(int i = gap; i < arr.length; i++) {
//用tmp记录将要排序的元素
int tmp = arr[i];
//用j来记录与将要排序的元素进行比较的元素
int j = i - gap;
while(j >= 0 && arr[j] > tmp) {
//将j交换到将要排序的元素的位置
arr[j + gap] = arr[j];
j-=gap;
}
//将要排序的元素放到它应该在的位置
arr[j + gap] = tmp;
}
}
return arr;
}
}
2.4 执行结果
[7, 2, 6, 5, 9, 4]
[2, 4, 5, 6, 7, 9]