java排序算法1(插入排序、希尔排序)
插入排序---稳定
平均时间复杂度 | 最好 | 最坏 | 空间复杂度 |
---|---|---|---|
O(n²) | n | O(n²) | O(1) |
//实现代码,不需要每次比都交换元素,减少交换次数
int[] arr = {1, 5, 7, 63, 4, 58, 45};
for (int i = 1; i < arr.length; i++) {
int tmp = arr[i];
int j;
for (j = i; j > 0 && tmp < arr[j - 1]; j--) {
arr[j]=arr[j-1];
}
arr[j]=tmp;
}
希尔排序---不稳定
希尔排序,也称 递减增量排序算法,是插入排序的一种更高效的改进版本。希尔排序是 非稳定排序算法。
希尔排序是基于插入排序的以下两点性质而提出改进方法的:
- 插入排序在对几乎已经排好序的数据操作时,效率高,即可以达到线性排序的效率,但插入排序一般来说是低效的,因为插入排序每次只能将数据移动一次
- 希尔排序是先将整个待排序的记录序列分割成为若干子序列分别进行直接插入排序,待整个序列中的记录“基本有序”时,再对全体记录进行依次直接插入排序。
思想
将待排序数组按照步长gap进行分组,然后将每组的元素利用直接插入排序的方法进行排序;每次再将gap折半减小,循环上述操作;当gap=1时,利用直接插入,完成排序。
可以看到步长的选择是希尔排序的重要部分。只要最终步长为1任何步长序列都可以工作。一般来说最简单的步长取值是初次取数组长度的一半为增量,之后每次再减半,直到增量为1。更好的步长序列取值可以参考维基百科。
平均时间复杂度 | 最好 | 最坏 | 空间复杂度 |
---|---|---|---|
O(nlog2 n) | n | O(nlog2 n) | O(1) |
int gap = arr.length;
while (gap > 1) {
gap = gap / 3 + 1;//最后一次为1
for (int i = 0; i < arr.length - gap; i++) {
for (int j = i + gap; j < arr.length; j += gap) {
if (arr[j-gap]>arr[j]){
int tmp=arr[j];
arr[j]=arr[j-gap];
arr[j-gap]=tmp;
}
}
}
}
总结
希尔排序更高效的原因是它权衡了子数组的规模和有序性。排序之初,各个子数组都很短,排序之后子数组都是部分有序的,这两种情况都很适合插入排序。