这一篇来学习希尔排序,希尔排序是直接插入排序的一种优化算法。
1.希尔排序概念
希尔排序(shell sort)是插入排序的一种。也称缩小增量排序,是直接插入排序算法的一种更高效的改进版本。希尔排序是非稳定排序算法,该方法因DL.Shell于1959年提出而得名。希尔排序是把纪录按下标的一定增量分组,对每组使用直接插入排序算法排序。随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个文件恰好被分层一组,算法便终止。
2.希尔排序思想
希尔排序的基本思想是:将数组列在一个表中并对列分别进行插入排序,重复这过程,不过每次用更长的列(步长更长了,列数更少了)来进行。最后整个表就只有一列了。将数组转换至表是为了更好地理解这算法,算法本身还是使用数组进行排序。
例如,假设有这样一组数[54 26 93 17 77 31 44 55 20],如果我们以步长(gap=4)为4开始进行排序,我们可以通过将这列表放在有4列的表中来更好地描述算法,这样他们就应该看起来是这样(竖着的元素是步长组成):
上面是原始需要排序的数列,现在把gap设置4,也就是这样第一次分组。
上面54下标是0,0+4 = 4, 所以54同组的下一个元素是下标为4的元素也就是77,同理77下一个元素是20.依次类推,第二组元素是26 31, 第三组元素是93 44, 第四组元素是17 55. 希尔排序就是把每一组元素采用直接插入排序算法,对元素位置交换,进行排序,第一次希尔排序之后数列为。
得到新数列,把gap设置成2,进行再一次分组。
然后把上面两组元素,采用直接插入排序算法,交换元素位置,形成新数列。
对上面这个数列,把gap设置为1,再次采用直接插入排序,最终排序完成。
根据数列元素个数,关键在于如何设置这个gap的值,这个值决定了最优情况下算法的时间复杂度。
3.希尔排序代码实现
python代码实现
# coding:utf-8
def shell_sort(alist):
"""希尔排序"""
n = len(alist)
# gap取值n的一半
gap = n // 2
# 最后一次gap需要等于1
while gap > 0:
for i in range(gap, n):
j = i
while j > 0:
if alist[j] < alist[j - gap]:
alist[j], alist[j - gap] = alist[j - gap], alist[j]
j -= gap
else:
break
# 缩短 gap步长
gap //= 2
if __name__ == "__main__":
alist = [54, 26, 93, 17, 77, 31, 44, 55, 20]
print(alist)
shell_sort(alist)
print(alist)
运行结果:
[54, 26, 93, 17, 77, 31, 44, 55, 20]
[17, 20, 26, 31, 44, 54, 55, 77, 93]
时间复杂度分析,如果gap一上来就是等于1,那就是前面一篇的直接插入排序算法,所以最坏时间复杂度是O(n^2), 至于什么情况下有最优的时间复杂度,这个需要数学方面知识去计算gap的取什么值才有最优解。
java代码实现过程
import java.util.Arrays;
public class ShellSort {
public static void main(String[] args){
int[] arr = {54, 26, 93, 17, 77, 31, 44, 55, 20};
System.out.println(Arrays.toString(arr));
shellSort(arr);
System.out.println(Arrays.toString(arr));
}
public static void shellSort(int[] arr){
int gap = arr.length/2;
while( gap > 0){
for(int i = gap; i < arr.length; i++){
int j = i;
//插入排序算法核心部分
while(j > 0){
if( j >= gap && arr[j] < arr[j - gap]){
int tmp = arr[j];
arr[j] = arr[j - gap];
arr[j - gap] = tmp;
j -= gap;
}else{
break;
}
}
}
gap /= 2;
}
}
}
注意上面的if判断条件中多写了一个j 和gap的判断,不然报空指针错误,运行结果:
[54, 26, 93, 17, 77, 31, 44, 55, 20]
[17, 20, 26, 31, 44, 54, 55, 77, 93]