漫谈经典排序算法二.docx

上传人:b****3 文档编号:26692881 上传时间:2023-06-21 格式:DOCX 页数:15 大小:81.09KB
下载 相关 举报
漫谈经典排序算法二.docx_第1页
第1页 / 共15页
漫谈经典排序算法二.docx_第2页
第2页 / 共15页
漫谈经典排序算法二.docx_第3页
第3页 / 共15页
漫谈经典排序算法二.docx_第4页
第4页 / 共15页
漫谈经典排序算法二.docx_第5页
第5页 / 共15页
点击查看更多>>
下载资源
资源描述

漫谈经典排序算法二.docx

《漫谈经典排序算法二.docx》由会员分享,可在线阅读,更多相关《漫谈经典排序算法二.docx(15页珍藏版)》请在冰豆网上搜索。

漫谈经典排序算法二.docx

漫谈经典排序算法二

11月热门下载资源TOP100强力推荐!

点击了解英特尔云计算

漫谈经典排序算法:

二、各种插入排序解析及性能比较

分类:

DataStructuresAndAlgorithms2011-09-1709:

55700人阅读评论(0)收藏举报

1、序言

这是《漫谈经典排序算法系列》第二篇,解析了各种插入排序算法。

主要包括:

直接插入排序、折半插入排序、表插入排序、希尔插入排序。

每一种算法的开头都叙述了引出该算法的原因,然后给出代码,最后分析算法效率及和其他插入排序相比,优劣在哪里。

各种排序算法的解析请参考如下:

《漫谈经典排序算法:

一、从简单选择排序到堆排序的深度解析》

《漫谈经典排序算法:

二、各种插入排序解析及性能比较》

《漫谈经典排序算法:

三、冒泡排序&&快速排序》

《漫谈经典排序算法:

四、归并排序》

《漫谈经典排序算法:

五、线性时间排序(计数、基数、桶排序)》

《漫谈经典排序算法:

六、各种排序算法总结》

注:

为了叙述方便,本文以及源代码中均不考虑A[0],默认下标从1开始。

2、直接插入排序

2.1引出

给定待排序序列A[1.....n],现假设A[1...i]已经有序,那么我们取出A[i+1]插入到序列A[1...i].这样有序序列记录数就增加了1.如此重复上述操作,不断取出记录插入有序序列,直到A[n]插入到有序序列,排序完成。

2.2代码

viewplaincopytoclipboardprint?

1.//直接插入排序

2.voidstraightInsertSort(int*a,intn)

3.{

4.inti,j;

5.inttemp;

6.//逐个记录插入有序序列

7.for(i=2;i<=n;i++){

8.temp=a[i];

9.//把a[i]插入有序序列

10.for(j=i-1;j>=1;j--){

11.if(temp

12.a[j+1]=a[j];

13.}else

14.break;

15.}

16.a[j+1]=temp;

17.}

18.}

2.3效率分析

容易看出,要插入的记录个数为n-1,其中关键字的比较次数和记录移动次数是依赖于给出的待排序序列是否基本有序。

在最佳情况下(待排序序列有序),比较次数和移动次数时间为o

(1),所以时间复杂度为o(n).在最坏情况下(待排序序列逆序)和平均时间均为o(n^2).从上述分析中可以看出,直接插入排序适合记录数比较少、给定序列基本有序的情况。

熟悉了排序过程我们发现,直接插入排序是一种稳定的原地排序算法。

3、折半插入排序

3.1引出

在直接插入排序过程中,我们是把一个记录插入到有序序列中,至于要插入到有序序列中的哪个位置呢?

采用的是顺序查找确定插入的位置。

显然对于有序序列,折半查找的效率要高,所以在寻找插入位置时可以用折半查找。

折半查找主要分为三步:

1、查找要插入的位置2、移位3、把记录插入相应的位置。

3.2代码

viewplaincopytoclipboardprint?

1.//折半查找

2.intbinarySearch(int*a,intlow,inthigh,intkey)

3.{

4.intmid=(low+high)/2;

5.if(low>high)

6.returnlow;

7.if(a[mid]==key)

8.returnmid;

9.elseif(key

10.returnbinarySearch(a,low,mid-1,key);

11.else

12.returnbinarySearch(a,mid+1,high,key);

13.}

14.

15.//折半插入排序

16.voidbinaryInsertSort(int*a,intn)

17.{

18.inti,j,site,temp;

19.for(i=2;i<=n;i++){

20.//1.折半查找要插入的位置

21.site=binarySearch(a,1,i,a[i]);

22.temp=a[i];

23.//2.移位

24.for(j=i;j>site;j--)

25.a[j]=a[j-1];

26.//3.插入a[i]

27.a[site]=temp;

28.}

29.}

3.3效率分析

折半插入排序是对直接插入排序的一种改进,这种改进只考虑了关键字比较次数,并没有减少移位次数,所以平均时间和最坏情况下(待排序序列逆序)时间复杂度o(n^2),如果记录数量很大的话,这两种情况下是优于直接插入排序。

再来看一下最佳情况(待排序序列有序),此时关键字比较次数并不为o

(1),时间复杂度为o(n*log2n)。

(其中折半查找时间复杂度o(log2n),这个在以后写查找的时候再分析,这里不做详细讲解。

)。

所以在记录数较小、待排序序列基本有序情况下直接插入排序优于折半插入排序。

此外,折半插入排序是不稳定的原地排序,实现起来也较复杂。

4、表插入排序

4.1引出

折半插入排序相对于直接插入排序来说减少了比较次数。

那么我们可不可以减少移动次数呢,答案是可以的。

于是就有了表插入排序,用一个静态链表来存储待排序序列,其他操作和直接插入排序很像。

主要步骤:

1、初始化链表2、取出要插入的记录3、遍历链表寻找插入位置4、记录插入链表中。

4.2代码

viewplaincopytoclipboardprint?

1.//静态链表

2.typedefstruct

3.{

4.intkey;//关键字

5.intnext;//指向下一个关键字的下标

6.}Node,*PNode;

7.

8.//表插入排序

9.voidtableInsertSort(PNodelist,intn)

10.{

11.intp,head;

12.inti;

13.//初始化

14.list[0].next=1;

15.list[1].next=0;

16.

17.//逐个插入

18.for(i=2;i<=n;i++){

19.head=0;

20.p=list[0].next;

21.//遍历链表,寻找插入位置

22.while(p!

=0&&list[p].key<=list[i].key){

23.head=p;

24.p=list[p].next;

25.}

26.if(p==0){//插入的值是最大值

27.list[i].next=p;

28.list[head].next=i;

29.}else{

30.list[i].next=p;

31.list[head].next=i;

32.}

33.

34.}

35.}

4.3效率分析

表插入排序也是对直接插入排序的一种改进,这种改进只减少了移动次数,并没有减少关键字比较次数,所以平均时间和最坏情况下(待排序序列逆序)时间复杂度o(n^2),如果记录数量很大的话,这两种情况下是优于直接插入排序。

再来看一下最佳情况(待排序序列有序),关键字比较次数并为o

(1),时间复杂度为o(n)。

此时和直接插入排序时间复杂度一样。

此外,表插入排序改变了记录的存储结构,无法顺序访问,是一种稳定的排序算法,实现起来也较复杂。

5、希尔插入排序

5.1引出

上述两种排序都是只考虑减少关键字比较次数或者只考虑减少关键字移动次数。

有没有别的改进办法呢?

我们注意到,直接插入排序适合于记录数较少、基本有序的情况。

于是我们可以先将整个待排序序列分割成若干子序列分别进行直接插入排序,整个序列基本有序时,再对序列进行一次直接插入排序。

这就是希尔排序。

5.2代码

viewplaincopytoclipboardprint?

1.//一趟增量为dk的希尔插入排序

2.voidshellInsert(int*a,intn,intdk)

3.{

4.inti,j,temp;

5.for(i=dk+1;i<=n;i+=dk){

6.temp=a[i];

7.for(j=i-dk;j>=0;j-=dk)

8.if(a[j]>temp)

9.a[j+dk]=a[j];

10.else

11.break;

12.a[j+dk]=temp;

13.}

14.}

15.

16.//希尔排序

17.voidshellSort(int*a,intn)

18.{

19.inti;

20.intdk[]={5,4,3,2,1};

21.for(i=0;i<5;i++)

22.shellInsert(a,6,dk[i]);

23.}

5.3效率分析

当给定序列记录量较大时,希尔排序性能优于直接插入排序。

再希尔排序的过程中,关键字是跳跃式移动的,这样就减少了移动次数。

希尔排序性能的分析是一个复杂的问题,时间与所取的增量有关。

增量选取的不好可能会大大降低排序效率。

6、附录

附录一、参考书籍

《数据结构》严蔚敏版

附录二、所有源代码

viewplaincopytoclipboardprint?

1.#include

2.

3.//直接插入排序

4.voidstraightInsertSort(int*a,intn)

5.{

6.inti,j;

7.inttemp;

8.//逐个记录插入有序序列

9.for(i=2;i<=n;i++){

10.temp=a[i];

11.//把a[i]插入有序序列

12.for(j=i-1;j>=1;j--){

13.if(temp

14.a[j+1]=a[j];

15.}else

16.break;

17.}

18.a[j+1]=temp;

19.}

20.}

21.

22.

23.voidmain()

24.{

25.inti;

26.inta[7]={0,3,5,8,9,1,2};//不考虑a[0]

27.straightInsertSort(a,6);

28.for(i=1;i<=6;i++)

29.printf("%-4d",a[i]);

30.printf("\n");

31.}

viewplaincopytoclipboardprint?

1.#include

2.

3.//折半查找

4.intbinarySearch(int*a,intlow,inthigh,intkey)

5.{

6.intmid=(low+high)/2;

7.if(low>high)

8.returnlow;

9.if(a[mid]==key)

10.returnmid;

11.elseif(key

12.returnbinarySearch(a,low,mid-1,key);

13.else

14.returnbinarySearch(a,mid+1,high,key);

15.}

16.

17.//折半插入排序

18.voidbinaryInsertSort(int*a,intn)

19.{

20.inti,j,site,temp;

21.for(i=2;i<=n;i++){

22.//1.折半查找要插入的位置

23.site=binarySearch(a,1,i,a[i]);

24.temp=a[i];

25.//2.移位

26.for(j=i;j>site;j--)

27.a[j]=a[j-1];

28.//3.插入a[i]

29.a[site]=temp;

30.}

31.}

32.

33.voidmain()

34.{

35.inti;

36.inta[7]={0,3,5,8,9,1,2};//不考虑a[0]

37.binaryInsertSort(a,6);

38.for(i=1;i<=6;i++)

39.printf("%-4d",a[i]);

40.printf("\n");

41.}

viewplaincopytoclipboardprint?

1.#include

2.#defineMAX10000

3.

4.//静态链表

5.typedefstruct

6.{

7.intkey;//关键字

8.intnext;//指向下一个关键字的下标

9.}Node,*PNode;

10.

11.//表插入排序

12.voidtableInsertSort(PNodelist,intn)

13.{

14.intp,head;

15.inti;

16.//初始化

17.list[0].next=1;

18.list[1].next=0;

19.

20.//逐个插入

21.for(i=2;i<=n;i++){

22.head=0;

23.p=list[0].next;

24.//遍历链表,寻找插入位置

25.while(p!

=0&&list[p].key<=list[i].key){

26.head=p;

27.p=list[p].next;

28.}

29.if(p==0){//插入的值是最大值

30.list[i].next=p;

31.list[head].next=i;

32.}else{

33.list[i].next=p;

34.list[head].next=i;

35.}

36.

37.}

38.}

39.

40.voidmain()

41.{

42.intp;

43.Nodelist[7]={MAX,0,3,0,5,0,8,0,9,0,1,0,2,0};

44.tableInsertSort(list,6);

45.p=list[0].next;

46.while(p!

=0){

47.printf("%-4d",list[p].key);

48.p=list[p].next;

49.}

50.printf("\n");

51.}

viewplaincopytoclipboardprint?

1.#include

2.

3.//一趟增量为dk的希尔插入排序

4.voidshellInsert(int*a,intn,intdk)

5.{

6.inti,j,temp;

7.for(i=dk+1;i<=n;i+=dk){

8.temp=a[i];

9.for(j=i-dk;j>=0;j-=dk)

10.if(a[j]>temp)

11.a[j+dk]=a[j];

12.else

13.break;

14.a[j+dk]=temp;

15.}

16.}

17.

18.//希尔排序

19.voidshellSort(int*a,intn)

20.{

21.inti;

22.intdk[]={5,4,3,2,1};

23.for(i=0;i<5;i++)

24.shellInsert(a,6,dk[i]);

25.}

26.

27.voidmain()

28.{

29.inti;

30.inta[7]={0,3,5,8,9,1,2};//不考虑a[0]

31.shellSort(a,6);

32.for(i=1;i<=6;i++)

33.printf("%-4d",a[i]);

34.printf("\n");

35.}

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 党团工作 > 入党转正申请

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1