数据结构:chapter8排序_第1页
数据结构:chapter8排序_第2页
数据结构:chapter8排序_第3页
数据结构:chapter8排序_第4页
数据结构:chapter8排序_第5页
已阅读5页,还剩147页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第八章排序2教学内容8.1概述8.2插入排序8.3交换排序8.4选择排序8.5归并排序21254925*160831.掌握排序的基本概念和各种排序方法的特点,并能加以灵活应用2.熟练掌握直接插入排序、折半插入排序、起泡排序、直接选择排序、快速排序的排序算法及其性能分析3.掌握希尔排序、归并排序、堆排序、基数排序的方法及其性能分析教学目标48.1概述1.什么是排序?将一组杂乱无章的数据按一定规律顺次排列起来。

2.排序的目的是什么?存放在数据表中按关键字排序

——便于查找!53.什么叫内部排序?什么叫外部排序?

若待排序记录都在内存中,称为内部排序;若待排序记录一部分在内存,一部分在外存,则称为外部排序。注:外部排序时,要将数据分批调入内存来排序,中间结果还要及时放入外存,显然外部排序要复杂得多。

64.排序算法的好坏如何衡量?时间效率——排序速度(比较次数与移动次数)空间效率——占内存辅助空间的大小稳定性——A和B的关键字相等,排序后A、B的先后次序保持不变,则称这种排序算法是稳定的。7记录序列以顺序表存储Typedefstruct{//定义每个记录(数据元素)的结构

KeyTypekey;//关键字

InfoTypeotherinfo;//其它数据项}RedType;Typedefstruct{//定义顺序表的结构

RedTyper[MAXSIZE+1];//存储顺序表的向量

//r[0]一般作哨兵或缓冲区

intlength;//顺序表的长度}SqList;#defineMAXSIZE20//设记录不超过20个typedefintKeyType;//设关键字为整型量(int型)8排序算法分类规则不同插入排序交换排序选择排序归并排序时间复杂度不同简单排序O(n2)先进排序O(nlog2n)98.2插入排序基本思想:

每步将一个待排序的对象,按其关键码大小,插入到前面已经排好序的一组对象的适当位置上,直到对象全部插入为止。即边插入边排序,保证子序列中随时都是排好序的10插入排序算法分类直接插入排序折半插入排序希尔排序最简单的排序法!11直接插入排序排序过程:整个排序过程为n-1趟插入,即先将序列中第1个记录看成是一个有序子序列,然后从第2个记录开始,逐个进行插入,直至整个序列有序。【13】,6,3,31,9,27,5,11【6,13】,3,31,9,27,5,11【3,6,13】,31,9,27,5,11【3,6,13,31】,9,27,5,11【3,6,9,13,31】,27,5,11【3,6,9,13,27,31】,5,11【3,5,6,9,13,27,31】,11【3,5,6,9,11,13,27,31】

例(13,6,3,31,9,27,5,11)1221254925*16080123456暂存21i=2i=3i=5i=4i=62525494925*25*49161625*08084921254925*21初态:164925*25211608完成!将序列存入顺序表L中,将L.r[0]作为哨兵(21,25,49,25*,16,08)*表示后一个2513直接插入排序voidInsertSort(SqList&L){inti,j;for(i=2;i<=L.length;++i)if(L.r[i].key<L.r[i-1].key)//将L.r[i]插入有序子表

{L.r[0]=L.r[i];//复制为哨兵

L.r[i]=L.r[i-1];for(j=i-2;L.r[0].key<L.r[j].key;--j) L.r[j+1]=L.r[j];//记录后移

L.r[j+1]=L.r[0];//插入到正确位置

}}14算法分析设对象个数为n,则执行n-1趟比较次数和移动次数与初始排列有关最好情况下:每趟只需比较1次,不移动总比较次数为

n-121254925*1608for(i=2;i<=L.length;++i)if(L.r[i].key<L.r[i-1].key)15最坏情况下:第i趟比较i次,移动i+1次21254925*1608算法分析比较次数移动次数if(L.r[i].key<L.r[i-1].key)

{

L.r[0]=L.r[i];//复制为哨兵

……L.r[j+1]=L.r[0];//插入到正确位置}16若出现各种可能排列的概率相同,则可取最好情况和最坏情况的平均情况平均情况比较次数和移动次数为n2/4时间复杂度为o(n2)空间复杂度为o(1)是一种稳定的排序方法21254925*160821254925*1608012345算法分析17折半插入排序直接插入排序减少关键字间的比较次数在插入r[i]时,利用折半查找法寻找r[i]的插入位置18i=2折半插入排序19i=3折半插入排序20i=4折半插入排序21i=5折半插入排序22i=6折半插入排序23StatusBInsertSort(SqList&L){for(i=2;i<=L.length;++i){L.r[0]=L.r[i];low=1;high=i-1;while(low<=high){m=(low+high)/2;if(LT(L.r[0].key,L.r[m].key))high=m-1;elselow=m+1;}for(j=i-1;j>=high+1;--j)L.r[j+1]=L.r[j];L.r[high+1]=L.r[0];}}//BInsertSort24折半查找比顺序查找快,所以折半插入排序就平均性能来说比直接插入排序要快它所需要的关键码比较次数与待排序对象序列的初始排列无关,仅依赖于对象个数。在插入第i个对象时,需要经过log2i+1次关键码比较,才能确定它应插入的位置算法分析25当n较大时,总关键码比较次数比直接插入排序的最坏情况要好得多,但比其最好情况要差在对象的初始排列已经按关键码排好序或接近有序时,直接插入排序比折半插入排序执行的关键码比较次数要少折半插入排序的对象移动次数与直接插入排序相同,依赖于对象的初始排列算法分析26减少了比较次数,但没有减少移动次数平均性能优于直接插入排序时间复杂度为o(n2)空间复杂度为o(1)是一种稳定的排序方法算法分析27希尔排序算法思想的出发点:直接插入排序在基本有序时,效率较高在待排序的记录个数较少时,效率较高基本思想:先将整个待排记录序列分割成若干子序列,分别进行直接插入排序,待整个序列中的记录“基本有序”时,再对全体记录进行一次直接插入排序。28希尔排序子序列的构成不是简单地“逐段分割”将相隔某个增量dk的记录组成一个子序列让增量dk逐趟缩短(例如依次取5,3,1)直到dk=1为止。技巧:小元素跳跃式前移最后一趟增量为1时,序列已基本有序平均性能优于直接插入排序优点:2938例:关键字序列T=(49,38,65,97,76,13,27,49*,55,04)0123456789104938659776132749*5504初态:第1趟(dk=5)第2趟(dk=3)第3趟(dk=1)4913134938276549*9755760427386549*9755135576045513270427044949*4949*76387665659797551327044949*3876659713270449*7697r[i]dk值较大,子序列中对象较少,速度较快;dk值逐渐变小,子序列中对象变多,但大多数对象已基本有序,所以排序速度仍然很快。30voidShellSort(SqList&L,intdlta[],intt){

//按增量序列dlta[0…t-1]对顺序表L作Shell排序

for(k=0;k<t;++k)

ShellInsert(L,dlta[k]);

//增量为dlta[k]的一趟插入排序}//ShellSort希尔排序算法(主程序)dk值依次装在dlta[t]中31voidShellInsert(SqList&L,int

dk){

for(i=dk+1;i<=L.length;++i)if(r[i].key<r[i-dk].key){

r[0]=r[i];

for(j=i-dk;j>0&&(r[0].key<r[j].key);j=j-dk) r[j+dk]=r[j];

r[j+dk]=r[0];

}}//对顺序表L进行一趟增量为dk的Shell排序,dk为步长因子//开始将r[i]插入有序增量子表//暂存在r[0]//关键字较大的记录在子表中后移//在本趟结束时将r[i]插入到正确位置希尔排序算法(其中某一趟的排序操作)32时间复杂度是n和d的函数:空间复杂度为o(1)是一种不稳定的排序方法算法分析O(n1.25)~O(1.6n1.25)—经验公式如何选择最佳d序列,目前尚未解决最后一个增量值必须为1,无除1以外的公因子不宜在链式存储结构上实现338.3交换排序基本思想:两两比较,如果发生逆序则交换,直到所有记录都排好序为止。起泡排序O(n2)快速排序O(nlog2n)34基本思想:每趟不断将记录两两比较,并按“前小后大”规则交换起泡排序21,25,49,25*,16,0821,25,25*,16,08,

4921,25,16,08,25*,4921,16,08,25,25*,4916,08,21,25,25*,4908,16,21,25,25*,4935起泡排序优点:每趟结束时,不仅能挤出一个最大值到最后面位置,还能同时部分理顺其他元素;

一旦下趟没有交换,还可提前结束排序main() { inta[11]; /*a[0]不用,之用a[1]~a[10]*/ inti,j,t; printf("\nInput10numbers:\n"); for(i=1;i<11;i++) scanf("%d",&a[i]); printf("\n");

for(j=1;j<=9;j++) for(i=1;i<=10-j;i++)

if(a[i]>a[i+1]) {t=a[i];a[i]=a[i+1];a[i+1]=t;}//交换

for(i=1;i<11;i++) printf("%d",a[i]);}37例3849657613273097

第一趟38496513273076第二趟384913273065第三趟3813273049第四趟13273038第五趟132730第六趟4938659776132730

初始关键字n=8384976971397279730971376767627301365276530651313494930492738273830381327第七趟排序后序列为:132730384965769738voidbubble_sort(SqList&L){intm,i,j,flag=1;RedTypex;m=n-1;while((m>0)&&(flag==1)){flag=0;for(j=1;j<=m;j++)if(L.r[j].key>L.r[j+1].key){flag=1;x=L.r[j];L.r[j]=L.r[j+1];L.r[j+1]=x;//交换

}//endifm--;}//endwhile}

39算法分析设对象个数为n比较次数和移动次数与初始排列有关只需1趟排序,比较次数为

n-1,不移动21254925*1608while((m>0)&&(flag==1)){flag=0;for(j=1;j<=m;j++)if(L.r[j].key>L.r[j+1].key){flag=1;x=L.r[j];L.r[j]=L.r[j+1];L.r[j+1]=x;}……最好情况下:4021254925*1608算法分析时间复杂度为o(n2)空间复杂度为o(1)是一种稳定的排序方法需n-1趟排序,第i趟比较n-i次,移动3(n-i)次最坏情况下:41快速排序基本思想:任取一个元素(如第一个)为中心所有比它小的元素一律前放,比它大的元素一律后放,形成左右两个子表;对各子表重新选择中心元素并依此规则调整,直到每个子表的元素只剩一个4221254925*16080123452125*1625160849pivotkey0821081625*21pivotkeypivotkey快速排序25*25492549pivotkey4349081625*2521440123 45678493838656597977676131327274949highlow49界点快速排序450123 45678493838656597977676131327274949highlow49界点快速排序460123 45678493838656597977676131327274949highlow49界点快速排序470123 45678493838656597977676131327274949highlow49界点快速排序480123 45678493838656597977676131327274949highlow49界点快速排序490123 45678493838656597977676131327274949highlow49界点快速排序500123 45678493838656597977676131327274949highlow49界点快速排序510123 45678493838656597977676131327274949highlow49界点快速排序520123 45678493838656597977676131327274949highlow49界点快速排序530123 45678493838656597977676131327274949highlow49界点快速排序540123 45678493838656597977676131327274949highlow49界点快速排序550123 45678493838656597977676131327274949highlow49界点快速排序560123 45678493838656597977676131327274949highlow49界点快速排序570123 45678273838136597497676139765274949highlow49界点快速排序580123 45678273838136597497676139765274949highlow49界点快速排序590123 45678273838136597497676139765274949highlow49界点快速排序600123 45678273838136597497676139765274949highlow49界点快速排序610123 45678273838136597497676139765274949highlow49界点快速排序620123 45678133827386597497676139765274949highlow49界点快速排序630123 45678133827386597497676139765274949highlow49界点快速排序640123 45678133827386597497676139765274949highlow49界点快速排序650123 45678133827386597497676139765274949highlow49界点快速排序660123 45678133827386597497676139765274949highlow49界点快速排序670123 45678133827386597497676139765274949highlow49界点快速排序680123 45678133827386597497676139765274949highlow49界点690123 45678133827386597497676139765274949highlow49界点700123 45678133827386597494976136576274997highlow49界点快速排序710123 45678133827386597494976136576274997highlow49界点快速排序720123 45678133827386597494976136576274997highlow49界点快速排序73①每一趟的子表的形成是采用从两头向中间交替式逼近法;②由于每趟中对各子表的操作都相似,可采用递归算法。快速排序74voidmain(){QSort(L,1,L.length);}voidQSort(SqList&L,intlow,inthigh){if(low<high){pivotloc=Partition(L,low,high);

Qsort(L,low,pivotloc-1);

Qsort(L,pivotloc+1,high)}}75intPartition(SqList&L,intlow,inthigh

)

{L.r[0]=L.r[low];pivotkey=L.r[low].key;

while(low<high){while(low<high&&L.r[high].key>=pivotkey)--high;L.r[low]=L.r[high];while(low<high&&L.r[low].key<=pivotkey)++low;L.r[high]=L.r[low];}

L.r[low]=L.r[0];returnlow;}76可以证明,平均计算时间是O(nlog2n)。实验结果表明:就平均计算时间而言,快速排序是我们所讨论的所有内排序方法中最好的一个。快速排序是递归的,需要有一个栈存放每层递归调用时参数(新的low和high)。最大递归调用层次数与递归树的深度一致,因此,要求存储开销为O(log2n)

。算法分析77算法分析最好:划分后,左侧右侧子序列的长度相同最坏:从小到大排好序,递归树成为单支树,每次划分只得到一个比上一次少一个对象的子序列,必须经过n-1趟才能把所有对象定位,而且第i

趟需要经过n-i

次关键码比较才能找到第i

个对象的安放位置算法分析时间效率:O(nlog2n)—每趟确定的元素呈指数增加空间效率:O(log2n)—递归要用到栈空间稳定性:不稳定—可选任一元素为支点。798.4选择排序基本思想:每一趟在后面n-i+1个中选出关键码最小的对象,作为有序序列的第i个记录802125*i=125164908最小者

08交换21,0825160825*4921i=2最小者

16交换25,1649i=3081625*2521最小者

21交换49,21简单选择排序814925*012345i=408162521最小者

25*无交换25*i=549最小者

25无交换2521160825160825*4921结果各趟排序后的结果简单选择排序82voidSelectSort(SqList&K){for(i=1;i<L.length;++i){//在L.r[i..L.length]中选择key最小的记录

k=i;for(j=i+1;j<=L.length;j++)if(L.r[j].key<L.r[k].key)k=j;if(k!=i)L.r[i]←→L.r[k];}}简单选择排序83算法分析时间复杂度:O(n²)空间复杂度:O(1)不稳定比较次数:移动次数最好情况:0最坏情况:3(n-1)84n个元素的序列{k1,k2,…,kn},当且仅当满足下列关系时,成为堆:堆排序什么是堆?如果将序列看成一个完全二叉树,非终端结点的值均小于或大于左右子结点的值。85(87,78,53,45,65,09,31,17,23)堆顶元素(根)为最小值或最大值(09,17,65,23,45,78,87,53,31)利用树的结构特征来描述堆,所以树只是作为堆的描述工具,堆实际是存放在线形空间中的。86小根堆

816

9

1

6

2

1110

5

4大根堆

1

6

812

916

2

11

5

148716

9

810

6

2

11

1

5

4

1

9

810

616

2

11

5

4×88判定(80,75,40,62,73,35,28,50,38,25,47,15)是否为堆807540627328355038254715完全二叉树大根堆89堆排序基本思想:如何建??如何调整??(1)将序列r[1..n]建初堆,交换r[1]和r[n],则r[n]为关键字最大的记录。(2)将r[1..n-1]重新调整为堆,交换r[1]和r[n-1],则r[n-1]为关键字次大的记录。(3)循环n-1次,直到交换了r[1]和r[2]为止,得到了一个非递减的有序序列r[1..n]。9030160240

4

70

58

312610

7[1][2][3][4][5][6][7]3060840701210如何将无序序列建成堆思考:有n个结点的完全二叉树,最后一个分支结点的标号是多少?n/29170160240

4

30

512

38610

7[1][2][3][4][5][6][7]7060124030810从第n/2个元素起,至第一个元素止,进行反复筛选堆9230160240

4

70

510

7[1][2][3][4][5][6][7]3060840701210无序序列建成堆-18

12

3

69330160240

4

70

512

810

7[1][2][3][4][5][6][7]3060124070810无序序列建成堆-1

3

6943016040

4

12810

7[1][2][3][4][5][6][7]3060124070810无序序列建成堆-2

3

6

270

5953017040

4

12810

7[1][2][3][4][5][6][7]3070124060810无序序列建成堆-2

3

6

260

596

7040

4

12810

7[1][2][3][4][5][6][7]3070124060810无序序列建成堆-3

3

6

2

60

530

197

3040

4

12810

7[1][2][3][4][5][6][7]7030124060810无序序列建成堆-3

3

6

2

60

570

198

6040

4

12810

7[1][2][3][4][5][6][7]7060124030810无序序列建成堆-3

3

6

2

5

70

130建堆完毕99将根结点r[1]与左、右子树根结点比较,并与小者交换重复直至叶子结点,得到新的堆交换r[1]和r[n]后,如何将r[1..n-1]重新调整,使之成为新堆?筛选堆的重新调整100

6040

4

12810

7[1][2][3][4][5][6][7]7060124030810

3

6

2

30

570

1堆的重新调整-1101堆的重新调整-1

6040

4

12810

7[1][2][3][4][5][6][7]

3

6

2

30

510

17060124030810707010×

×

60106010104040102堆的重新调整-2

4010

4

12810

7[1][2][3][4][5][6][7]

3

6

2

30

560

160401210308107070×

×

103堆的重新调整-2

4010

4

126010

7[1][2][3][4][5][6][7]

3

6

2

30

58

1840121030601070706060104堆的重新调整-2

3010

4

126010

7[1][2][3][4][5][6][7]

3

6

28

540

1403012108601070706060105堆的重新调整-3

3010

4

126010

7[1][2][3][4][5][6][7]

3

6

28

540

1403012108601070706060106堆的重新调整-3

3010

4

126010

7[1][2][3][4][5][6][7]

3

6

28

58

1830121086010707060604040107堆的重新调整-3

108

4

126010

7[1][2][3][4][5][6][7]

3

6

28

530

1301012886010707060604040108堆的重新调整-4

108

4

126010

7[1][2][3][4][5][6][7]

3

6

28

530

1301012886010707060604040109堆的重新调整-4

1030

4

126010

7[1][2][3][4][5][6][7]

3

6

28

58

18101230860107070606040403030110堆的重新调整-5

1030

4

86010

7[1][2][3][4][5][6][7]

3

6

28

512

11210830860107070606040403030111堆的重新调整-5

1030

4

86010

7[1][2][3][4][5][6][7]

3

6

28

58

18108308601070706060404030301212112堆的重新调整-5

1030

4

86010

7[1][2][3][4][5][6][7]

3

6

28

58

18108308601070706060404030301212113堆的重新调整-5

830

4

86010

7[1][2][3][4][5][6][7]

3

6

28

510

11088308601070706060404030301212114堆的重新调整-6

830

4

86010

7[1][2][3][4][5][6][7]

3

6

28

510

11088308601070706060404030301212115堆的重新调整-6

830

4

86010

7[1][2][3][4][5][6][7]

3

6

28

58

18883086010707060604040303012121010116算法分析时间效率:O(nlog2n)空间效率:O(1)稳定性:不稳定适用于n较大的情况1178.5归并排序归并:将两个或两个以上的有序表组合成一个新有序表2-路归并排序排序过程初始序列看成n个有序子序列,每个子序列长度为1两两合并,得到n/2个长度为2或1的有序子序列再两两合并,重复直至得到一个长度为n的有序序列为止118将两个顺序表合并成一个有序表0123 44913659776780AB0123 4567Cijk1190123 44913659776780AB0123 4567Cijk71200123 44913659776780AB0123 4567Cijk71210123 44913659776780AB0123 4567Cijk7131220123 44913659776780AB0123 4567Cijk713491230123 44913659776780AB0123 4567Cijk713491240123 44913659776780AB0123 4567Cijk71349651250123 44913659776780AB0123 4567Cijk71349651260123 44913659776780AB0123 4567Cijk7134965761270123 44913659776780AB0123 4567Cijk7134965761280123 44913659776780AB0123 4567Cijk713496576801290123 44913659776780AB0123 4567Cijk713496576801300123 44913659776780AB0123 4567Cijk71349657680B表的元素都已移入C表,只需将A表的剩余部分移入C表即可1310123 44913659776780AB0123 4567Cijk7134965768097132例初始关键字:[49][38][65][97][76][13][27]一趟归并后:[3849][6597][1376][27]二趟归并后:[38496597][132776]三趟归并后:[13273849657697]133算法分析时间效率:O(nlog2n)空间效率:O(n)稳定性:稳定134以扑克牌排序为例。每张扑克牌有两个“排序码”:花色和面值。其有序关系为:

花色:

面值:2<3<4<5<6<7<8<9<10<J<Q<K<A

可以把所有扑克牌排成以下次序:

2,…,

A,

2,…,

A,

2,…,

A,

2,

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论