第10章内排序_第1页
第10章内排序_第2页
第10章内排序_第3页
第10章内排序_第4页
第10章内排序_第5页
已阅读5页,还剩85页未读 继续免费阅读

下载本文档

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

文档简介

1、第第10章章 内内 排排 序序10.6 基数排序基数排序10.1 排序的基本概念排序的基本概念10.2 插入排序插入排序10.3 交换排序交换排序10.4 选择排序选择排序10.5 归并排序归并排序10.7 各种内排序方法的比较和选择各种内排序方法的比较和选择10.1 排序的基本概念排序的基本概念 所谓排序,是要整理表中的记录,使之按关键字递增所谓排序,是要整理表中的记录,使之按关键字递增(或递减)有序排列。其确切定义如下:(或递减)有序排列。其确切定义如下: 输入:输入:n个记录个记录,R0,R1,Rn-1,其相应的关键字分别为其相应的关键字分别为k0,k1,kn-1。 输出:输出:Ri,0

2、,Ri,1,Ri,n-1,使得使得ki,0ki,1ki,n-1 (或或ki,0ki,1ki,n-1)。本章仅考虑递增排序本章仅考虑递增排序 当待排序记录的关键字均不相同时,排序的结果是惟一当待排序记录的关键字均不相同时,排序的结果是惟一的的, ,否则排序的结果不一定唯一。如果待排序的表中否则排序的结果不一定唯一。如果待排序的表中, ,存在有存在有多个关键字相同的记录多个关键字相同的记录, ,经过排序后这些具有相同关键字的记经过排序后这些具有相同关键字的记录之间的相对次序保持不变录之间的相对次序保持不变, ,则称这种排序方法是则称这种排序方法是稳定稳定的;反的;反之之, ,若具有相同关键字的记录

3、之间的相对次序发生变化若具有相同关键字的记录之间的相对次序发生变化, ,则称则称这种排序方法是这种排序方法是不稳定不稳定的。的。 在排序过程中,若整个表都是放在内存中处理,排序时在排序过程中,若整个表都是放在内存中处理,排序时不涉及数据的内、外存交换,则称之为不涉及数据的内、外存交换,则称之为内排序内排序;反之,若排;反之,若排序过程中要进行数据的内、外存交换,则称之为序过程中要进行数据的内、外存交换,则称之为外排序外排序。 算法的稳定性算法的稳定性内排序和外排序内排序和外排序内排序的基本方法内排序的基本方法内部排序的过程是一个逐步扩大记录的有序序内部排序的过程是一个逐步扩大记录的有序序列长度

4、的过程。列长度的过程。经过一趟排序经过一趟排序有序序列区无 序 序 列 区有序序列区无 序 序 列 区正序和反序正序和反序若待排序的表中元素已按关键字排好序,称此表中元素若待排序的表中元素已按关键字排好序,称此表中元素为为正序正序;反之,若待排序的表中元素的关键字顺序正好和排;反之,若待排序的表中元素的关键字顺序正好和排好序的顺序相反,称此表中元素为好序的顺序相反,称此表中元素为反反序。序。排序的分类排序的分类根据排序算法是否基于关键字的比较,将排序算法分为根据排序算法是否基于关键字的比较,将排序算法分为基于比较的排序算法基于比较的排序算法和和不基于比较的排序算法不基于比较的排序算法。像插入排

5、序、。像插入排序、交换排序、选择排序和归并排序都是基于比较的排序算法;交换排序、选择排序和归并排序都是基于比较的排序算法;而基数排序是不基于比较的排序算法。而基数排序是不基于比较的排序算法。 待排序的顺序表类型的类型定义如下:待排序的顺序表类型的类型定义如下: typedef int KeyType; /定义关键字类型定义关键字类型 typedef struct /记录类型记录类型 KeyType key; /关键字项关键字项 InfoType data; /其他数据项其他数据项,类型为类型为InfoType RecType; /排序的记录类型定义排序的记录类型定义 存放数据的结构:存放数据的

6、结构:10.2 插入排序插入排序 插入排序的基本思想是:每次将一个待排序的记录插入排序的基本思想是:每次将一个待排序的记录, ,按其按其关键字大小插入到前面已经排好序的子表中的适当位置关键字大小插入到前面已经排好序的子表中的适当位置, ,直到直到全部记录插入完成为止。全部记录插入完成为止。 两种插入排序方法:两种插入排序方法: (1 1)直接插入排序(含二分插入排序)直接插入排序(含二分插入排序) (2 2)希尔排序)希尔排序10.2.1 直接插入排序直接插入排序 假设待排序的记录存放在数组假设待排序的记录存放在数组R0.n-1中,排序过程的某中,排序过程的某一中间时刻,一中间时刻,R被划分成

7、两个子区间被划分成两个子区间R0.i-1和和Ri.n-1,其中:,其中:前一个子区间是已排好序的有序区,后一个子区间则是当前未前一个子区间是已排好序的有序区,后一个子区间则是当前未排序的部分,不妨称其为无序区。排序的部分,不妨称其为无序区。 直接插入排序的基本操作是将当前无序区的第直接插入排序的基本操作是将当前无序区的第1个记录个记录Ri插入到有序区插入到有序区R0.i-1中适当的位置上,使中适当的位置上,使R0.i变为新的有变为新的有序区。这种方法通常称为序区。这种方法通常称为增量法增量法,因为它每次使有序区增加,因为它每次使有序区增加1个记录。个记录。 R0Ri-1 有序区有序区 RiRn

8、-1 无序区无序区 一趟排序一趟排序 R0Ri-1 Ri Ri+1Rn-1 有序区有序区 无序区无序区 R0jRij=i-1插入位置插入位置在有序区中插入在有序区中插入Ri的过程的过程void InsertSort(RecType R,int n) /对对R0.n-1按递增有序进行直接插入排序按递增有序进行直接插入排序 int i,j; RecType temp; for (i=1;i=0 & temp.keyj且且Ri.key=Rj.key时,本算法将时,本算法将Ri插入在插入在Rj的后面,使的后面,使Ri和和Rj的相对位置保持不变,所以直接插入的相对位置保持不变,所以直接插入排序是

9、一种排序是一种稳定的排序方法稳定的排序方法。 Rj Ri 有序区有序区Ri插入在插入在Rj的后面的后面10.2.2 折半折半插入排序插入排序查找采用查找采用折半折半查找方法,称为二分插入排序或折半插入排序。查找方法,称为二分插入排序或折半插入排序。void InsertSort1(RecType R,int n)int i,j,low,high,mid; RecType tmp; for (i=1;in;i+) tmp=Ri; /将将Ri保存到保存到tmp中中low=0;high=i-1;while (low=high) /在在Rlow.high中查找插入的位置中查找插入的位置 mid=(lo

10、w+high)/2;/取中间位置取中间位置 if (tmp.key=high+1;j-)/记录后移记录后移 Rj+1=Rj;Rhigh+1=tmp;/插入插入 折半插入排序的元素移动次数与直接插入排序相同,不折半插入排序的元素移动次数与直接插入排序相同,不同的仅是变分散移动为集合移动。在同的仅是变分散移动为集合移动。在R0.i-1中查找插入中查找插入Ri的位置,折半查找的平均关键字比较次数为的位置,折半查找的平均关键字比较次数为log2(i+1)-1,平均,平均移动元素的次数为移动元素的次数为i/2+2,所以平均时间复杂度为:,所以平均时间复杂度为:)()221) 1(log(2112nOii

11、ni就平均性能而言,折半查找优于顺序查找,所以折就平均性能而言,折半查找优于顺序查找,所以折半插入排序也优于直接插入排序。折半插入排序的空间半插入排序也优于直接插入排序。折半插入排序的空间复杂度为复杂度为O(1)。10.2.3 希尔排序希尔排序 希尔排序也是一种插入排序方法希尔排序也是一种插入排序方法,实际上是一种分组插入方实际上是一种分组插入方法。法。 基本思想:基本思想: 先取定一个小于先取定一个小于n的整数的整数d1作为第一个增量,把表的全部记作为第一个增量,把表的全部记录分成录分成d1个组,所有距离为个组,所有距离为d1的倍数的记录放在同一个组中,的倍数的记录放在同一个组中,在各组内进

12、行直接插入排序;在各组内进行直接插入排序; 然后取第二个增量然后取第二个增量d2(d1),重复上述的分组和排序,),重复上述的分组和排序,直至所取的增量直至所取的增量dt=1(dtdt-1d20) for (i=gap;i=0 & tmp.keyRj.key) Rj+gap=Rj;j=j-gap; Rj+gap=tmp;gap=gap/2;/减小增量减小增量 例例10.2 设待排序的表有设待排序的表有10个记录个记录,其关键字分别为其关键字分别为9,8,7,6,5,4,3,2,1,0。说明采用希尔排序方法进行排序的过程。说明采用希尔排序方法进行排序的过程。 9 8 7 6 5 4 3

13、2 1 0 初初始始状状态态 (连连线线部部分分为为下下一一趟趟作作准准备备) 4 3 2 1 0 9 8 7 6 5 d=5 (d=5 执执行行结结果果) 0 1 2 3 4 5 6 7 8 9 d=2 (d=2 执执行行结结果果) 0 1 2 3 4 5 6 7 8 9 d=1 (d=1 执执行行结结果果) 希尔排序的时间复杂度约为希尔排序的时间复杂度约为O(n1.3)。为什么希尔排序比直接插入排序好?为什么希尔排序比直接插入排序好?例如:有例如:有10个元素要排序。个元素要排序。希尔排序希尔排序直接插入排序直接插入排序大约时间大约时间=102=100d=5:分为:分为5组,时间约为组,时

14、间约为5*2220d=2:分为:分为2组,时间约为组,时间约为2*5250d=1:分为:分为1组,几乎有序,时间约为组,几乎有序,时间约为1080希尔排序算法不稳定的反例希尔排序算法不稳定的反例希尔排序法是一种不稳定的排序算法。希尔排序法是一种不稳定的排序算法。例如,若希尔排序分为两组:例如,若希尔排序分为两组:3,10,7,8,20和和5,8,2,1,6,显,显然,第然,第1组的组的8排列在第排列在第2组的组的8的后面,两组采用直接插入排序的后面,两组采用直接插入排序后的结果为:后的结果为:3,7,8,10,20和和1,2,5,6,8,这样第,这样第1组的组的8排列到第排列到第2组的组的8的

15、前面,它们的相对位置发生了改变。的前面,它们的相对位置发生了改变。思考题:思考题:希尔排序中的有序区是全局有序吗?希尔排序中的有序区是全局有序吗?10.3 交换排序交换排序 交换排序的基本思想:两两比较待排序记录的关键字交换排序的基本思想:两两比较待排序记录的关键字,发现两个记录的次序相反时即进行交换发现两个记录的次序相反时即进行交换,直到没有反序的记直到没有反序的记录为止。录为止。 两种交换排序两种交换排序: (1)冒泡排序)冒泡排序 (2)快速排序)快速排序10.3.1 冒泡排序冒泡排序 冒泡排序的基本思想冒泡排序的基本思想:通过无序区中相邻记录关键字间的:通过无序区中相邻记录关键字间的比

16、较和位置的交换,使关键字最小的记录如气泡一般逐渐往比较和位置的交换,使关键字最小的记录如气泡一般逐渐往上上“漂浮漂浮”直至直至“水面水面”。 整个算法是从最下面的记录开始,对每两个相邻的关键字整个算法是从最下面的记录开始,对每两个相邻的关键字进行比较进行比较,且使关键字较小的记录换至关键字较大的记录之上,且使关键字较小的记录换至关键字较大的记录之上,使得经过一趟冒泡排序后,关键字最小的记录到达最上端,使得经过一趟冒泡排序后,关键字最小的记录到达最上端,接着再在剩下的记录中找关键字次小的记录,并把它换在第接着再在剩下的记录中找关键字次小的记录,并把它换在第二个位置上。依次类推,一直到所有记录都有

17、序为止。二个位置上。依次类推,一直到所有记录都有序为止。 一趟排序一趟排序 R0 有序区有序区 无序区无序区 Ri-1 Ri Rn-1 Ri+1 R0 Ri Ri-1 将无序区中将无序区中最小记录放最小记录放在在 Ri Ri+1 Rn-1 有序区有序区 无序区无序区 void BubbleSort(RecType R,int n) int i,j; RecType temp; for (i=0;ii;j-) /比较找本趟最小关键字的记录比较找本趟最小关键字的记录 if (Rj.keyRj-1.key) temp=Rj; /Rj与与Rj-1进行交换进行交换 Rj=Rj-1; Rj-1=temp;

18、 全局有序区全局有序区 Ri Rn-1用交换找最小记录放到用交换找最小记录放到Ri处处 例例10.3 设待排序的表有设待排序的表有10个记录个记录,其关键字分别为其关键字分别为9,8,7,6,5,4,3,2,1,0。说明采用冒泡排序方法进行排序的过程。说明采用冒泡排序方法进行排序的过程。 初始关键字初始关键字 9 8 7 6 5 4 3 2 1 0 i=0 0 9 8 7 6 5 4 3 2 1 i=1 0 1 9 8 7 6 5 4 3 2 i=2 0 1 2 9 8 7 6 5 4 3 i=3 0 1 2 3 9 8 7 6 5 4 i=4 0 1 2 3 4 9 8 7 6 5 i=5

19、0 1 2 3 4 5 9 8 7 6 i=6 0 1 2 3 4 5 6 9 8 7 i=7 0 1 2 3 4 5 6 7 9 8 i=8 0 1 2 3 4 5 6 7 8 9 思考题:思考题:冒泡冒泡排序中的有序区是全局有序吗?排序中的有序区是全局有序吗? 在有些情况下,在第在有些情况下,在第i(in-1)趟时已排好序了,)趟时已排好序了,但仍执行后面几趟的比较。实际上,一旦算法中某一趟但仍执行后面几趟的比较。实际上,一旦算法中某一趟比较时不出现记录交换,说明已排好序了,就可以结束比较时不出现记录交换,说明已排好序了,就可以结束本算法。本算法。 为此得到改进冒泡排序算法如下:为此得到改

20、进冒泡排序算法如下:void BubbleSort(RecType R,int n) int i,j; bool exchange;RecType temp; for (i=0;ii;j-)/比较比较,找出最小关键字的记录找出最小关键字的记录 if (Rj.keyRj-1.key) temp=Rj; Rj=Rj-1;Rj-1=temp; exchange=true; if (exchange=false) return; /中途结束算法中途结束算法 最好的情况(关键字在记录序列中顺序有序):最好的情况(关键字在记录序列中顺序有序): 只需进行一趟冒泡只需进行一趟冒泡“比较比较”的次数:的次数:

21、最坏的情况(关键字在记录序列中逆序有序):最坏的情况(关键字在记录序列中逆序有序): 需进行需进行n-1趟冒泡趟冒泡“比较比较”的次数:的次数:0“移动移动”的次数:的次数:“移动移动”的次数:的次数:n-121110)n(n)in(ni 2131320)n(n)in(ni 10.3.2 快速排序快速排序 快速排序是由冒泡排序改进而得的。快速排序是由冒泡排序改进而得的。 基本思想基本思想:在待排序的:在待排序的n n个记录中任取一个记录(通常取个记录中任取一个记录(通常取第一个记录),把该记录放入适当位置后第一个记录),把该记录放入适当位置后, ,数据序列被此记录数据序列被此记录划分成两部分。

22、所有关键字比该记录关键字小的记录放置在前划分成两部分。所有关键字比该记录关键字小的记录放置在前一部分一部分, ,所有比它大的记录放置在后一部分所有比它大的记录放置在后一部分, ,并把该记录排在这并把该记录排在这两部分的中间两部分的中间( (称为该记录归位称为该记录归位) ),这个过程称作一趟快速排序。,这个过程称作一趟快速排序。 首先对无序的记录序列进行首先对无序的记录序列进行“一次划分一次划分”,之后分别对分割,之后分别对分割所得两个子序列所得两个子序列“递归递归”进行快速排序。进行快速排序。无 序 的 记 录 序 列无序记录子序列(1)无序子序列(2)基准基准一次划分分别进行快速排序需要确

23、定排序的序列,采用什么存储结构?需要确定排序的序列,采用什么存储结构?52 49 80 36 14 58 61 97 23 75stlowhigh设设 Rs=52 为枢轴为枢轴 将将 Rhigh.key 和基准的关键字进行比较,要求和基准的关键字进行比较,要求Rhigh.key 基准的关键字基准的关键字 将将 Rlow.key 和基准的关键字进行比较,要求和基准的关键字进行比较,要求Rlow.key 基基准的关键字准的关键字high23low80high14low52例如例如R052lowhighhighhighlow 可见,经过可见,经过“一次划分一次划分” ,将关键字序列,将关键字序列 5

24、2, 49, 80, 36, 14, 58, 61, 97, 23, 75 调整为调整为: 23, 49, 14, 36, (52) 58, 61, 97, 80, 75 在调整过程中,设立了两个指针:在调整过程中,设立了两个指针: low 和和high,它们的初值,它们的初值分别为:分别为: s 和和 t。 之后逐渐减小之后逐渐减小 high,增加,增加 low,并保证,并保证 Rhigh.key52,和,和 Rlow.key52, ,否则进行记录的否则进行记录的“交交换换”。 以后对所有的两部分分别重复上述过程,直至每部分以后对所有的两部分分别重复上述过程,直至每部分内只有一个记录为止。内

25、只有一个记录为止。简而言之,每趟使表的简而言之,每趟使表的第一个元素第一个元素放入适当位置,将放入适当位置,将表一分为二,对子表按递归方式继续这种划分,直至划分表一分为二,对子表按递归方式继续这种划分,直至划分的子表长为的子表长为1。void QuickSort(RecType R,int s,int t) /对对Rs至至Rt的元素进行快速排序的元素进行快速排序 int i=s,j=t;RecType temp; if (si & Rj.keytemp.key) j-; Ri=Rj; while (ij & Ri.keytemp.key) i+; Rj=Ri; Ri=temp;

26、 QuickSort(R,s,i-1); /对左区间递归排序对左区间递归排序 QuickSort(R,i+1,t); /对右区间递归排序对右区间递归排序 划分划分 例例10.4 设待排序的表有设待排序的表有10个记录个记录,其关键字分别为其关键字分别为6,8,7,9,0,1,3,2,4,5。说明采用快速排序方法进行排序的过程。说明采用快速排序方法进行排序的过程。 6 8 7 9 0 1 3 2 4 5 5 4 2 3 0 1 6 9 7 8 (a) 第 1 次划分 6 8 7 9 0 1 3 2 4 5 5 4 2 3 0 1 6 9 7 8 (b) 第 2 次划分 1 4 2 3 0 5 6

27、 8 7 9 0 1 3 2 4 5 5 4 2 3 0 1 6 9 7 8 1 4 2 3 0 5 0 1 2 3 4 6 8 7 9 0 1 3 2 4 5 5 4 2 3 0 1 6 9 7 8 1 4 2 3 0 5 0 1 2 3 4 2 3 4 (c) 第 3 次划分 (d) 第 4 次划分 6 8 7 9 0 1 3 2 4 5 5 4 2 3 0 1 6 9 7 8 1 4 2 3 0 5 0 1 2 3 4 2 3 4 (e) 第 5 次划分 3 4 6 8 7 9 0 1 3 2 4 5 5 4 2 3 0 1 6 9 7 8 1 4 2 3 0 5 0 1 2 3 4 2

28、 3 4 (f) 第 6 次划分 3 4 8 7 9 6 8 7 9 0 1 3 2 4 5 5 4 2 3 0 1 6 9 7 8 1 4 2 3 0 5 0 1 2 3 4 2 3 4 (g) 第 7 次划分 3 4 8 7 9 7 8 nkavgavgavgknTkTnCnnT1)() 1(1)(则可得结果:则可得结果:结论结论: 快速排序的时间复杂度为快速排序的时间复杂度为O(nlog2n)由此可得快速排序所需时间的平均值为:由此可得快速排序所需时间的平均值为:平均所需栈空间为平均所需栈空间为O(log2n)。nk-1n-k1次划分的时间次划分的时间Tavg(n)=Cnlog2n。10

29、.4 选择排序选择排序 选择排序的基本思想是:每一趟从待排序的记录中选出关选择排序的基本思想是:每一趟从待排序的记录中选出关键字最小的记录,顺序放在已排好序的子表的最后,直到全键字最小的记录,顺序放在已排好序的子表的最后,直到全部记录排序完毕。部记录排序完毕。 两种选择排序方法:两种选择排序方法: (1)简单选择排序(或称直接选择排序)简单选择排序(或称直接选择排序) (2)堆排序)堆排序10.4.1 直接选择排序直接选择排序基本思想:第基本思想:第i趟排序开始时趟排序开始时,当前有序区和无序区分别为当前有序区和无序区分别为R0.i-1和和Ri.n-1(0in-1),该趟排序则是从当前无序区)

30、,该趟排序则是从当前无序区中选出关键字最小的记录中选出关键字最小的记录Rk,将它与无序区的第,将它与无序区的第1个记录个记录Ri交换,使交换,使R0.i和和Ri+1.n-1分别变为新的有序区和新的无序分别变为新的有序区和新的无序区。区。 假设排序过程中,待排记录序列的状态为:假设排序过程中,待排记录序列的状态为:有序序列有序序列R0.i-1无序序列无序序列 Ri.n-1 第第 i 趟趟简单选择排序简单选择排序从中选出关键字最从中选出关键字最小的记录小的记录有序序列有序序列R0.i-1无序序列无序序列 Ri+1.n-1void SelectSort(RecType R,int n) int i,

31、j,k; RecType temp; for (i=0;in-1;i+) /做第做第i趟排序趟排序 k=i;for (j=i+1;jn;j+) /在在i.n-1中选中选key最小的最小的Rk if (Rj.keyRk.key) k=j; /k记下的最小关键字所在的位置记下的最小关键字所在的位置if (k!=i) /交换交换Ri和和Rk temp=Ri; Ri=Rk; Rk=temp; 全局有序区全局有序区 Ri Rn-1用选择找最小记录放到用选择找最小记录放到Ri处处 例例10.5 设待排序的表有设待排序的表有10个记录,其关键字分别为个记录,其关键字分别为6,8,7,9,0,1,3,2,4,

32、5。说明采用直接选择排序方法进行排序的过。说明采用直接选择排序方法进行排序的过程。程。 初始关键字初始关键字 6 8 7 9 0 1 3 2 4 5 i=0 0 8 7 9 6 1 3 2 4 5 i=1 0 1 7 9 6 8 3 2 4 5 i=2 0 1 2 9 6 8 3 7 4 5 i=3 0 1 2 3 6 8 9 7 4 5 i=4 0 1 2 3 4 8 9 7 6 5 i=5 0 1 2 3 4 5 9 7 6 8 i=6 0 1 2 3 4 5 6 7 9 8 i=7 0 1 2 3 4 5 6 7 9 8 i=8 0 1 2 3 4 5 6 7 8 9 对对 n 个记录进

33、行简单选择排序,所需进行的个记录进行简单选择排序,所需进行的 关键字间关键字间的比较次数的比较次数 总计为:总计为:移动记录的次数,最小值为移动记录的次数,最小值为 0, 最大值为最大值为3(n-1) 。21120)n(n)in(ni 10.4.2 堆排序堆排序 堆排序是一树形选择排序,它的特点是,在排序过程中,堆排序是一树形选择排序,它的特点是,在排序过程中,将将R1.n看成是一棵看成是一棵完全二叉树完全二叉树的顺序存储结构,利用完全二叉的顺序存储结构,利用完全二叉树中双亲结点和孩子结点之间的内在关系,在当前无序区中选择树中双亲结点和孩子结点之间的内在关系,在当前无序区中选择关键字最大(或最

34、小)的记录。关键字最大(或最小)的记录。 堆的定义是:堆的定义是:n个关键字序列个关键字序列K1,K2,Kn称为称为堆堆,当且仅当该当且仅当该序列满足如下性质(简称为堆性质):序列满足如下性质(简称为堆性质): (1)KiK2i 且且 KiK2i+1 或或 (2)KiK2i 且且 KiK2i+1(1i n/2 ) 满足第(满足第(1)种情况的堆称为小根堆,满足第()种情况的堆称为小根堆,满足第(2)种情况的)种情况的堆称为大根堆。下面讨论的堆是大根堆。堆称为大根堆。下面讨论的堆是大根堆。12, 36, 27, 65, 40, 34, 98, 81, 73, 55, 49是小根堆是小根堆例如例如

35、:12, 36, 27, 65, 40, 14, 98, 81, 73, 55, 49不是堆不是堆rir2i r2i+1 若将该数列视作完全二叉树,则若将该数列视作完全二叉树,则 r2i 是是 ri 的左孩子;的左孩子; r2i+1 是是 ri 的右孩子。的右孩子。1236276549817355403498例如例如:是堆是堆14不不 堆排序的关键是构造堆堆排序的关键是构造堆,这里采用筛选算法建堆。这里采用筛选算法建堆。 所谓所谓“筛选筛选”指的是,对一棵左指的是,对一棵左/右子树均为堆的完全二右子树均为堆的完全二叉树,叉树,“调整调整”根结点使整个二叉树也成为一个堆。根结点使整个二叉树也成为

36、一个堆。堆堆筛选筛选堆堆98814973556412362740例如例如:是大根堆是大根堆12但在但在 98 和和 12 进行互换之后,它就不是堆了,进行互换之后,它就不是堆了,因此,需要对它进行因此,需要对它进行“筛选筛选”。98128173641298比较比较比较比较void sift(RecType R,int low,int high) /调整堆的算法调整堆的算法 int i=low,j=2*i; /Rj是是Ri的左孩子的左孩子 RecType temp=Ri; while (j=high) if (jhigh & Rj.keyRj+1.key) j+; if (temp.ke

37、y=1;i-) /循环建立初始堆循环建立初始堆 sift(R,i,n); for (i=n;i=2;i-) /进行进行n-1次循环次循环,完成推排序完成推排序 temp=R1; /将第一个元素同当前区间内将第一个元素同当前区间内R1对换对换 R1=Ri;Ri=temp; sift(R,1,i-1); /筛选筛选R1结点结点,得到得到i-1个结点的堆个结点的堆 例例10.6 设待排序的表有设待排序的表有10个记录,其关键字分别为个记录,其关键字分别为6,8,7,9,0,1,3,2,4,5。说明采用堆排序方法进行排序的过程。说明采用堆排序方法进行排序的过程。 6 8 7 9 0 2 4 1 3 5

38、 9 8 7 6 5 2 4 1 3 0 (a) 初始状态初始状态 (b) 建立的初始堆建立的初始堆 0 8 7 6 5 2 4 1 3 8 6 7 4 5 2 0 1 3 (a) 交换交换 9 与与 0,输出,输出 9 (b) 筛选调整筛选调整 0 6 7 4 5 2 1 3 (c) 交换交换 8 与与 0,输出,输出 8 7 6 3 4 5 2 1 0 2 6 3 4 5 1 0 (d) 筛选调整筛选调整 (e) 交换交换 7 与与 2,输出,输出 7 6 5 3 4 2 1 0 (f) 筛选调整筛选调整 堆排序过程:堆排序过程: 0 5 3 4 2 1 5 4 3 0 2 1 (g) 交

39、换交换 6 与与 0,输出,输出 6 (h) 筛选调整筛选调整 (i) 交换交换 5 与与 1,输出,输出 5 1 4 3 0 2 4 2 3 0 1 (j) 筛选调整筛选调整 1 2 3 2 3 2 0 (k) 交换交换 4 与与 1,输出,输出 4 (l) 筛选调整筛选调整 (m) 交换交换 3 与与 1,输出,输出 3 0 2 1 2 0 1 (n) 筛选调整筛选调整 1 1 0 1 0 (o) 交换交换 2 与与 1,输出,输出 2 (p) 筛选调整筛选调整 (q) 交换交换 1 与与 0,输出,输出 1 0 1 0 (r) 输出输出 0 堆排序的时间复杂度分析:堆排序的时间复杂度分析

40、:1. 对深度为对深度为 k 的堆,的堆,“筛选筛选”所需进行的关键字所需进行的关键字比较的次数至多为比较的次数至多为2(k-1);3. 调整调整“堆顶堆顶” n-1 次,总共进行的关键次,总共进行的关键 字比较的次数不超过字比较的次数不超过 2 ( log2(n-1) + log2(n-2) + +log22) 2n( log2n ) 因此,堆排序的时间复杂度为因此,堆排序的时间复杂度为O(nlogn)。思考题:思考题:选择排序中的有序区是全局有序吗?选择排序中的有序区是全局有序吗?10.5 归并排序归并排序 归并排序是多次将两个或两个以上的有序表合并成一个归并排序是多次将两个或两个以上的有

41、序表合并成一个新的有序表。最简单的归并是直接将两个有序的子表合并成新的有序表。最简单的归并是直接将两个有序的子表合并成一个有序的表。一个有序的表。 在内部排序中,通常采用的是在内部排序中,通常采用的是2-路归并排序。即:将路归并排序。即:将两个位置相邻的记录有序子序列。两个位置相邻的记录有序子序列。归并为一个记录的有序序列。归并为一个记录的有序序列。有有 序序 序序 列列 Rl.n有序子序列有序子序列 Rl.m有序子序列有序子序列 Rm+1.n这个操作对顺序表而言,是轻而易举的。这个操作对顺序表而言,是轻而易举的。void Merge(RecType R,int low,int mid,int

42、 high) RecType *R1; int i=low,j=mid+1,k=0; /k是是R1的下标的下标,i、j分别为第分别为第1、2段的下标段的下标 R1=(RecType *)malloc(high-low+1)*sizeof(RecType); while (i=mid & j=high) if (Ri.key=Rj.key) /将第将第1段中的记录放入段中的记录放入R1中中 R1k=Ri; i+;k+; else /将第将第2段中的记录放入段中的记录放入R1中中 R1k=Rj; j+;k+; Merge()实现了一次归并实现了一次归并 :空间复杂度空间复杂度为为O(hig

43、h-low+1)while (i=mid) /将第将第1段余下部分复制到段余下部分复制到R1 R1k=Ri; i+;k+; while (j=high) /将第将第2段余下部分复制到段余下部分复制到R1 R1k=Rj; j+;k+; for (k=0,i=low;i=high;k+,i+) /将将R1复制回复制回R中中 Ri=R1k; free(R1); void MergePass(RecType R,int length,int n) int i; for (i=0;i+2*length-1n;i=i+2*length) /归并归并length长的两相邻子表长的两相邻子表 Merge(R,

44、i,i+length-1,i+2*length-1); if (i+length-1n) /余下两个子表余下两个子表,后者长度小于后者长度小于length Merge(R,i,i+length-1,n-1); /归并这两个子表归并这两个子表MergePass()实现了一趟归并实现了一趟归并 二路归并排序算法如下:二路归并排序算法如下:void MergeSort(RecType R,int n) int length; for (length=1;length=0;i-) /从低位到高位做从低位到高位做d趟排序趟排序 /123以以“321”存储存储 for (j=0;jdatai-0; /找第

45、找第k个链队个链队 if (headk=NULL) /进行分配进行分配,即采用尾插法建立单链表即采用尾插法建立单链表 headk=p; tailk=p; else tailk-next=p; tailk=p; p=p-next; /取下一个待排序的元素取下一个待排序的元素 分分配配 p=NULL; for (j=0;jnext=headj; t=tailj; t-next=NULL; /最后一个结点的最后一个结点的next域置域置NULL 收收集集排序完成后,排序完成后,p指向的是一个有序单链表指向的是一个有序单链表 例例10.8 设待排序的表有设待排序的表有10个记录,其关键字分别为个记录,其关键字分别为75,23,98,44,57,12,29,64,38,82。说明采用基数排序方法进行。说明采用基数排序方

温馨提示

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

评论

0/150

提交评论