您的位置:首页 > 其它

内部排序之插入排序、希尔排序

2014-03-22 20:08 267 查看
排序算法是我们在程序设计过程中需要经常用到的算法,好的排序算法可以有效提高排序效率。

排序算法根据占用内存方式的不同分为两种:内存排序算法和外部排序算法。内部排序算法是指排序工作能够在主存中完成,而不需要访问外存的排序方法。不能只在主存中完成而必须借助外存来完成的排序称为外部排序。

内部排序算法根据排序策略的不同,大体上可以归纳为5类:插入排序,选择排序,交换排序,归并排序和基数排序。其中,插入排序以插入排序和希尔排序这两种方法为主;选择排序则主要包括选择排序和堆排序;交换排序主要包括冒泡法排序和快速排序。

下面将具体介绍5中排序方式的排序思想:插入排序,希尔排序,堆排序,归并排序和快速排序。我们将假设n是所要进行排序的整型元素个数,数据起始位置为0.

1.插入排序

插入排序应该是最简单的一种排序算法,对n个整型元素进行排序,则需要比较n-1趟。对于第p(1 =< p<=n-1)趟比较,,能够保证从位置0到位置p上的元素为已排序状态。

下面通过引入具体的数据来实现该思想:

元素位置 0 1 2 3 4 5

初始 元素 34 8 64 51 32 21

第一趟比较后 8 34 64 51 32 21

第二趟比较后 8 34 64 51 32 21

第三趟比较后 8 34 51 64 32 21

第四趟比较后 8 32 34 51 64 21

第五趟比较后 8 21 32 34 51 64

上面n=6个元素,比较了5趟,第p趟比较都能保证从位置0到位置p上的元素排好序。

插入排序的函数实现如下:

void InsertSort(int a[],int n)//-------------------------------------1.插入排序
{
int j,i,tmp;
for(i=1;i<n;i++)//比较n-1趟
{
tmp=a[i];
for(j=i;j>=0 && a[j-1] > tmp;j--)
a[j]=a[j-1];
a[j]=tmp;
}
}


插入排序的算法排序的时间复杂度分析:由于嵌套循环中的每一个都花费n次迭代,当以从大到小的顺序输入时,则得到插入排序时间复杂度的上界为O(N^2);如果输入的数据已经从大到小排好序,内层循环每次都是立即终止,此时就得到插入排序时间复杂度的下界O(N)。插入排序的平均时间复杂度为O(N^2)。

2.希尔排序(shell sort)

希尔排序算法属于插入类排序算法,它通过比较相距一定间隔的元素来工作,各趟比较所用的距离随着算法的进行而减小,直到只比较相邻元素的最后一趟排序为止, 因此 这种排序方法又被人称之为缩小增量排序( diminishing increment sort )。

算法思想:对于n个整型元素(位置从0到n-1),选取一个正整数d1<n,把所有序号相隔d1的数组元素放一组,组内进行直接插入排序,然后取d2<d1,重复上述分组和排序操作,直至di=1,即将所有元素放到一个组内进行插入排序为止。这里就有一个问题:如何选择增量序列di? 增量序列di的一种流行的选择是使用希尔排序的发明人shell 建议的序列,即让d1=n/2,d(i+1)=d(i)/2。

下面将通过引入具体数据来介绍该思想:

元素位置 0 1 2 3 4 5 6 7 8 9

初始元素 48 38 65 97 76 13 27 49 55 4

d1=5排序后 13
27 49
55 4 48
38 65 97 76

d2=2排序后 4
27 13 48 38 55 49 65
97 76

d3=1排序后 4 13 27 38 48 49 55 65 76 97

该方法实质上是分组插入算法,对于上面的10个整型元素,增量序列的取值依次为5,2,1

希尔排序的函数实现:

void ShellSort(int a[],int n)
{
int tmp,i,j,increment;
for(increment = n/2;increment > 0;increment /= 2)//增量序列
for(i = increment;i < n;i++)  //对每一个步长的增量序列进行类插入排序
{
tmp=a[i];
for(j = i;j >=increment;j-=increment)
{
if(a[j-increment] > tmp)
a[j] = a[j-increment];//
else
{
break;
}
}
a[j] = tmp;
}
}

也可以这样(一个意思):

void ShellSort(int a[],int n)
{
int tmp,i,j,increment;
for(increment = n/2;increment > 0;increment /= 2)//增量序列
for(i = increment;i < n;i++)  //对每一个步长的增量序列进行类插入排序
{
tmp=a[i];
for(j = i;j >=increment && a[j-increment]>tmp;j-=increment)
{
a[j] = a[j-increment];
}
a[j] = tmp;
}
}


希尔排序的时间复杂度:使用希尔排序的最坏情形运行时间为O(n^2)。使用Hibbard增量的希尔排序的最坏情形运行时间为O(N^1.5),Hibbard增量排序的增量序列为

{2^k-1,2^(k-1)-1,.....,7,3,1}.Sedgewick提出的几种增量序列,其最坏情形运行时间为O(n^(4/3))。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: