一.前提
1.为简单起见,讨论从小到大的整数排序
2.只讨论基于比较的排序(< = >有定义)
3.只讨论内部排序
4.稳定性:任意两个相等的数据,排序前后相对位置不发生变化
二.补充
2.逆序对:对于下标i、j,如果i < j,而且a[i] > a[j]
,则称(i,j)或者(a[i],a[j])为逆序对
2.希尔排序:目标是克服插入排序每次只交换相邻两个元素的缺点
3.插入排序
三.希尔排序原理
希尔排序是把记录按下表的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个文件恰被分成一组,算法便终止。
四.实现
//希尔排序是依靠插入排序来实现的
public int[] Shell_Sort(int[] array){
int gap = array.length/2; //希尔增量,取数组的一半
//增量每次循环减半,最小为1
while(gap > 0){
//num是目前进行到的待排序分组的第二个元素
//比如{1,2,3,4,5,6},增量为3,表示分了三组[1,4][2,5][3,6]。
//所以我们要进行三次的插入排序,把这三组进行排序
//这里的分组是逻辑上的分组,物理上他们还是位于array数组内的,但我们把它们看作是不同的分组
//由此我们可以看到,如果是直接插入排序,对于4来说,他要和{1,2,3}进行比较
//而希尔排序,对于4来说,它只要和1进行比较,两个下标相差gap
//分组[1,4]的第二个元素映射到array数组中就是第gap个元素
for( int num = gap ; num < array.length ; num++){
int j;
int temp = array[num];
for(j = num; j >= gap && temp < array[j-gap]; j -= gap)
array[j] = array[j-gap];
array[j] = temp;
}
gap /= 2;
}
return array;
}
五.时间复杂度
1.我们来看下它的时间复杂度的组成:
(1)最外层的while循环T1(n) = O(logn)
(2)里面的插入排序的时间复杂度
- 最好情况:
数组是顺序的,插入排序时间复杂度为 T2(n) = O(n)
总的时间复杂度:T(n) = nlogn - 最坏情况:
最坏情况与增量的选择有关
设总共有x次循环,由于数据放的很巧妙,前x-1次循环数组完全没改变。导致最后一次插入排序,数组才改变且排序好
emm不是很懂,看这个文章
希尔排序&选择排序&时间复杂度分析
总的时间复杂度:T(n) = n2
六.空间复杂度
所有操作都是在一个数组内进行的,没有额外的添加空间
S(n) = O(1)