每日一算法|希尔排序---第六天
Posted 江小湖资源分享平台
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了每日一算法|希尔排序---第六天相关的知识,希望对你有一定的参考价值。
希尔排序
( 动图演示)
算法
原理
希尔排序,也称递减增量排序算法,是的一种更高效的改进版本。但希尔排序是非稳定排序算法。
希尔算法的总体思路是分组插入,先将整个待排序的记录序列分割成为若干子序列分别进行直接插入排序,待整个序列中的记录"基本有序"时,再对全体记录进行依次直接插入排序,理解难点在分组上。
比较相隔较远距离(称为增量)的数,使得数移动时能跨过多个元素,则进行一次比较就可能消除多个元素交换。算法先将要排序的一组数按某个增量d分成若干组,每组中记录的下标相差d.对每组中全部元素进行排序,然后再用一个较小的增量对它进行,在每组中再进行排序。当增量减到1时,整个要排序的数被分成一组,排序完成。
增量的选取为数据个数除以2,以此进行到1为止。
直接看上面的文字的话很难理解,接下来我们通过例子的讲解来让大家明白。
例:对{2 、6、8、9、1、3、4、7、5、0}进行排序
增量的选取:10/2=5,5/2=2,2/1=1。所以我们选取的增量为5、2、1。
第一趟排序:
增量为5,分为5组,分别为{2、3}{6、4}{8、7}{9、5}{1、0},大家注意看排序的方法,前五个和后五个分别配对。接下来,对每个分组进行直接插入排序,然后把每个分组的最小值取出来按顺序排好,最大值跟在后面,排好后得到的数列是这样的{2、4、7、5、0、3、6、8、9、1},第一趟完成。
第二趟排序:
增量为2,把第一趟排好的数列分为2组,分组的时候注意,数2取一值,所得分组分别为{2、7、0、6、9}{4、5、3、8、1},每组进行插入排序,得到{0、2、6、7、9}{1、3、4、5、8},之后每个分组按照从小到大依次取出一个进行排序,得到{0、1、2、3、6、4、7、5、9、8},第二趟排序完成。
第三趟排序:
增量为1,对第二趟排序后的数列进行插入排序即可。
希尔排序较难理解,读者需要认真体会一下,尤其是分组后排序的地方。
C语言
//由小到大
//希尔排序
void shellSort( long int array[], int length)
{
int i;
int j;
int k;
int gap; //gap是分组的步长
long int temp; //希尔排序是在直接插入排序的基础上实现的,所以仍然需要哨兵
for(gap=length/2; gap>0; gap=gap/2)
{
//以GAP为间隔分组
for(i=0; i<gap; i++)
{
/*
每一组做插入排序
*/
for(j=i+gap; j<length; j=j+gap)
{
//如果当前元素比这一组中的前一个元素要小
if(array[j] < array[j - gap])
{
//记录当前这个更小的元素 temp
temp = array[j]; //哨兵
k = j - gap;
//把这一组中之前所有比temp小的元素都往后挪一个位置
while(k>=0 && array[k]>temp)
{
array[k + gap] = array[k];
k = k - gap;
}
//把挪出来的空位,放入temp
array[k + gap] = temp;
}
}
}
}
}
Java
public class ShellSort {
public static void main(String[] args) {
int arr[]={2 、6、8、9、1、3、4、7、5、0};
System.out.println("排序前:"+Arrays.toString(arr));
sort(arr);
System.out.println("排序后:"+Arrays.toString(arr));
}
public static void sort(int arr[]) {
int d=arr.length/2;
int x,j,k=1;
while(d>=1) {
for(int i=d;i<arr.length;i++) {
x=arr[i];
j=i-d;
//直接插入排序,会向前找所适合的位置
while(j>=0 && arr[j]>x) {
//交换位置
arr[j+d]=arr[j];
j=j-d;
}
arr[j+d]=x;
}
d=d/2;
System.out.println("第"+ k++ +"趟:"+Arrays.toString(arr));
}
}
}
Python
def shellSort(arr):
import math
gap=1
while(gap < len(arr)/2):
gap = gap*2+1
while gap > 0:
for i in range(gap,len(arr)):
temp = arr[i]
j = i-gap
while j >=0 and arr[j] > temp:
arr[j+gap]=arr[j]
j-=gap
arr[j+gap] = temp
gap = math.floor(gap/2)
return arr
◆ ◆ ◆ ◆ ◆
总结:有人可能要问,既然希尔算法那么难理解,为什么还要用它呢?其实是有原因的,前面也提到过,希尔算法是插入排序算法的改进高效版本,
希尔排序是基于插入排序的以下两点性质而提出改进方法的:
1.插入排序在对几乎已经排好序的数据操作时,效率高,即可以达到线性排序的效率。
2.但插入排序一般来说是低效的,因为插入排序每次只能将数据移动一位。
总之就是说,通过对无序数列整理成相对有序的数列,从而加快对数列的插入排序。
以上是关于每日一算法|希尔排序---第六天的主要内容,如果未能解决你的问题,请参考以下文章