数据结构-排序

合集下载

数据结构实验报告八-快速排序

数据结构实验报告八-快速排序

实验8 快速排序1.需求分析(1)输入的形式和输入值的范围:第一行是一个整数n,代表任务的件数。

接下来一行,有n个正整数,代表每件任务所用的时间。

中间用空格或者回车隔开。

不对非法输入做处理,及假设用户输入都是合法的。

(2)输出的形式:输出有n行,每行一个正整数,从第一行到最后一行依次代表着操作系统要处理的任务所用的时间。

按此顺序进行,则使得所有任务等待时间最小。

(3)程序所能达到的功能:在操作系统中,当有n 件任务同时来临时,每件任务需要用时ni,输出所有任务等待的时间和最小的任务处理顺序。

(4)测试数据:输入请输入任务个数:9请输入任务用时:5 3 4 2 6 1 5 7 3输出任务执行的顺序:1 2 3 3 4 5 5 6 72.概要设计(1)抽象数据类型的定义:为实现上述程序的功能,应以整数存储用户的第一个输入。

并将随后输入的一组数据储存在整数数组中。

(2)算法的基本思想:如果将任务按完成时间从小到大排序,则在完成前一项任务时后面任务等待的时间总和最小,即得到最小的任务处理顺序。

采取对输入的任务时间进行快速排序的方法可以在相对较小的时间复杂度下得到从小到大的顺序序列。

3.详细设计(1)实现概要设计中定义的所有数据类型:第一次输入的正整数要求大于零,为了能够存储,采用int型定义变量。

接下来输入的一组整数,数据范围大于零,为了排序需要,采用线性结构存储,即int类型的数组。

(2)实现程序的具体步骤:一.程序主要采取快速排序的方法处理无序数列:1.在序列中根据随机数确定轴值,根据轴值将序列划分为比轴值小和比轴值大的两个子序列。

2.对每个子序列采取从左右两边向中间搜索的方式,不断将值与轴值比较,如果左边的值大于轴值而右边的小于轴值则将二者交换,直到左右交叉。

3.分别对处理完毕的两个子序列递归地采取1,2步的操作,直到子序列中只有一个元素。

二.程序各模块的伪代码:1、主函数int main(){int n;cout<<"请输入任务个数:";cin>>n;int a[n];cout<<"请输入任务用时:";for(int i=0;i<n;i++) cin>>a[i];qsort(a,0,n-1); //调用“快排函数”cout<<"任务执行的顺序:";for(int i=0;i<n;i++) cout<<a[i]<<" "; //输出排序结果}2、快速排序算法:void qsort(int a[],int i,int j){if(j<=i)return; //只有一个元素int pivotindex=findpivot(a,i,j); //调用“轴值寻找函数”确定轴值swap(a,pivotindex,j); //调用“交换函数”将轴值置末int k=partition(a,i-1,j,a[j]); //调用“分割函数”根据轴值分割序列swap(a,k,j);qsort(a,i,k-1); //递归调用,实现子序列的调序qsort(a,k+1,j);}3、轴值寻找算法://为了保证轴值的“随机性”,采用时间初始化种子。

数据结构教程 第九章 排序

数据结构教程 第九章 排序
2 插入排序


9.2.3 希尔排序
3.算法



void ShellSort() { gap=n/2;//初次增量取序列元素个数n的一半为步长 while(gap>0) { for(i=gap+1;i<=n;i++) { j=i-gap; while(j>0) { if(r[j]>r[j+gap]) { x=r[j];r[j]=r[j+gap];r[j+gap]=x; j=j-gap; }//对子序列作直接插入排序 else j=0; } } gap=gap/2;}//每次减半,直至步长为1 上一页 }
上一页
下一页
9.3 快速排序法


9.3.2 快速排序
3【例9-5】对数据序列:70, 75, 69, 32, 88, 18, 16, 58进行快速排序如图9-3所示。 4.算法


void QuickSort(int low, int high)//递归形式的快速排序 { int pivotpos; if(low<high) { pivotpos=Partition(low,high); QuickSort(low,pivotpos-1);//对低子表递归排序 QucikSort(pivotpos+1,high);//对高子表递归排序 } }
9.2 插入排序


9.2.2 二分插入排序
3.算法



void BinsSort() { for(i=2;i<=n;i++) { r[0]=r[i];low=1;high=i-1;//将r[i]暂存到r[0] while(low<=high) //在r[low..high]中折半查找有序插入的位置 { m=(low+high)/2;//折半 if(r[0].key<r[m].key) high=m-1;//插入点在低半区 else low=m+1;//插入点在高半区 } for(j=i-1;j>high+1;--j) r[j+1]=r[j];//记录后移 r[high+1]r[0];//插入 } 上一页 下一页

数据结构第9章 排序

数据结构第9章 排序

数据结构第9章排序数据结构第9章排序第9章排名本章主要内容:1、插入类排序算法2、交换类排序算法3、选择类排序算法4、归并类排序算法5、基数类排序算法本章重点难点1、希尔排序2、快速排序3、堆排序4.合并排序9.1基本概念1.关键字可以标识数据元素的数据项。

如果一个数据项可以唯一地标识一个数据元素,那么它被称为主关键字;否则,它被称为次要关键字。

2.排序是把一组无序地数据元素按照关键字值递增(或递减)地重新排列。

如果排序依据的是主关键字,排序的结果将是唯一的。

3.排序算法的稳定性如果要排序的记录序列中多个数据元素的关键字值相同,且排序后这些数据元素的相对顺序保持不变,则称排序算法稳定,否则称为不稳定。

4.内部排序与外部排序根据在排序过程中待排序的所有数据元素是否全部被放置在内存中,可将排序方法分为内部排序和外部排序两大类。

内部排序是指在排序的整个过程中,待排序的所有数据元素全部被放置在内存中;外部排序是指由于待排序的数据元素个数太多,不能同时放置在内存,而需要将一部分数据元素放在内存中,另一部分放在外围设备上。

整个排序过程需要在内存和外存之间进行多次数据交换才能得到排序结果。

本章仅讨论常用的内部排序方法。

5.排序的基本方法内部排序主要有5种方法:插入、交换、选择、归并和基数。

6.排序算法的效率评估排序算法的效率主要有两点:第一,在一定数据量的情况下,算法执行所消耗的平均时间。

对于排序操作,时间主要用于关键字之间的比较和数据元素的移动。

因此,我们可以认为一个有效的排序算法应该是尽可能少的比较和数据元素移动;第二个是执行算法所需的辅助存储空间。

辅助存储空间是指在一定数据量的情况下,除了要排序的数据元素所占用的存储空间外,执行算法所需的存储空间。

理想的空间效率是,算法执行期间所需的辅助空间与要排序的数据量无关。

7.待排序记录序列的存储结构待排序记录序列可以用顺序存储结构和和链式存储结构表示。

在本章的讨论中(除基数排序外),我们将待排序的记录序列用顺序存储结构表示,即用一维数组实现。

《数据结构》排序》PPT课件.ppt

《数据结构》排序》PPT课件.ppt

结束
结束
[50 65] 76 [97]
50 [65]
结束
结束
[13 38 38 49 50 65 76 97]
(b) 快速排序的全过程
图9.4 快速排序示例
算法9.4 快速排序算法。
void Quick_Sort(NODE array[],int start,int end)
/* 对从array[start]到array[end]的记录快速排序 */
}
}
9.1.2 希尔排序
希尔排序是一种步长递减的插入排序,又称为
“缩小增量排序”。该排序方法是,将直接插入分成插入 步长由大到小不同的若干趟来进行。初始,步长较大,相 当于把待排记录序列分成若干子序列,各子序列中记录的 间隔为步长距离,由于子序列的长度小,所以子序列的插 入排序的效率较高。以后各趟逐步减小步长,随着步长的 减小,子序列的长度在增加,但子序列中包含了上一趟经 过大的步长插入排序的结点,因此,已有部分结点有序, 这样,在排序中记录移动的次数就少,排序的效率也就高。 最后一趟是步长为1,即:对整个序列直接插入排序,但 这时整个序列已基本有序,只要做少量记录移动,就可将 该序列排成有序。
问题,但它的排序速度要比直接插 入排序快,另外,它是一种不稳定 排序
9.2 交换排序
交换排序基本思想:比较二个待排序记录的关键字, 若为逆序,则交换位置,反之,保持原序。
9.2.1 冒泡(简单交换排序)
冒泡排序的方法是:首先比较array[n-1].key和array[n-2]. key,若为逆序则交换之,然后比较array[n-2].key和array[n3].key,依此类推,直到比较array[1].key和array[0].key,称为 一趟“冒泡”,其结果是将具有最小关键字的记录排到序列 的第1个位置上。然后再array[n-1]到array[1]之间进行一趟“ 冒泡”,将具有次小关键字的记录排到序列的第2个位置上。 依此类推,直到第n-1趟,在array[n-1]和array[n-2]之间进行“ 冒泡”后,待排序序列已排成有序。

《数据结构排序》PPT课件

《数据结构排序》PPT课件

讨论:若记录是链表结构,用直接插入排序行否?折半插入 排序呢?
答:直接插入不仅可行,而且还无需移动元素,时间效率更 高!但链表无法“折半”!
折半插入排序的改进——2-路插入排序见教材P267。 (1)基本思想: P267 (2)举 例:P268 图10.2 (3)算法分析:移动记录的次数约为n2/8
13 20 39 39 42 70 85
i=8
0
1
2
3
4
5
6
7
8
Hj
折半插入排序的算法分析 • 折半查找比顺序查找快,所以折半插入排序
就平均性能来说比直接插入排序要快。
• 在插入第 i 个对象时,需要经过 log2i +1
次关键码比较,才能确定它应插入的位置。 • 折半插入排序是一个稳定的排序方法。
for ( j=i-1;j>=high+1;--j) L.r [j+1] = L.r [j];// 记录
后移
L.r [high+1] = L.r [0];
// 插入
} // for
} // BInsertSort
初始
30 13 70 85 39 42 6 20
012345678
i=2 13
30
13
数逐渐变多,由于前面工作的基础,大多数对象已基本有 序,所以排序速度仍然很快。
时间效率: O(n1.25)~O(1.6n1.25)——经验公式
空间效率:O(1)——因为仅占用1个缓冲单元 算法的稳定性:不稳定——因为49*排序后却到了49的前面
希尔排序算法(主程序)
参见教材P272
void ShellSort(SqList &L,int dlta[ ],int t){

数据结构复习--排序和查找

数据结构复习--排序和查找

数据结构复习--排序和查找现在正在学习查找和排序,为了节省时间提⾼效率,就正好边学习边整理知识点吧!知识点⼀:⼆分查找/折半查找1.⼆分查找的判定树(选择题)下列⼆叉树中,可能成为折半查找判定树(不含外部结点)的是: (4分)1.2.3.4.注:折半查找判定树是⼀棵⼆叉排序树,它的中序遍历结果是⼀个升序序列,可以在选项中的树上依次填上相应的元素。

虽然折半查找可以上取整也可以下取整但是⼀个查找判定树只能有⼀种取整⽅式。

如果升序序列是偶数个,那么终点应该偏左多右少。

在2选项中,由根节点左⼦树4个节点⽽右⼦树5个节点可以确定⽤的是向下取整策略,但是它的左⼦节点在左⼦树种对应的终点左边2个,右边个,明显是上取整策略,策略没有统⼀,所以是错的。

其他的选项类似分析。

2.⼆分查找法/折半查找法已知⼀个长度为16的顺序表L,其元素按关键字有序排列。

若采⽤⼆分查找法查找⼀个L中不存在的元素,则关键字的⽐较次数最多是: (2分)1. 72. 63. 54. 4 注:⼀次找到最边界的那⼀个树的情况下有最多次数 这个题中结点数16是个偶数:第⼀次(0+15)/2 7 第⼆次(8+15)/2 11第三次(12+15)/2 14 第四次(14+15)/2 14 第五次(15+15)/2 15(下取整的就向右计算求最多次数)第⼀次(0+15)/2 8 第⼆次(0+7)/2 4 第三次(0+3)/2 2 第四次(0+1)/2 0第五次(0+0)/2 0(下取整的话就向左求最多次数)若结点数是奇数15:第⼀次(0+14)/2 7 第⼆次( 0+6)/2 3 第三次(0+2)/2 1第四次(0+0)/2 0第⼀次(0+14)/2 7 第⼆次(8+14)/2 11 第三次(12+14)/2 13第四次(14+14)/2 0这时候向左或者向右都是OK的(因为得到的数都是能够被2整除的)但是划重点了折半查找⼀个有序表中不存在的元素,若向下取整,则要最多⽐较[log2n]+1次,若向上取整,则要最多⽐较[log2(n+1)],其实就是求树的深度.(这⼀块⾃⼰的说法可能不够准确,希望⼤家看到有问题的可以指出来)结合实际,我们⽤[log2n]+1来算更简单并且计算[log2n]要取整数,因为可能会存在不是满⼆叉树的情况。

数据结构第七章 排序

数据结构第七章 排序

name 张涛 赵亮
冯博远 王强 李燕
7.2
基本原理
插入排序
每次将一个待排序的对象,按其关键字大小, 插入到前面已经排序好的一组对象的适当位臵上, 直到对象全部插入为止。
直接插入排序(Insert Sort)
希尔排序(Shell Sort)
7.2.1
直接插入排序
R[1]---R[i-1]
08 08
16 16
第三次
08
16
21
25* 25
49
希尔排序中d(间隔量)的取法 Shell最初的方案是 d= n/2, d=d/2, 直到d=1; Knuth的方案是d= d/3+1;
其它方案有:都取奇数为好;d互质为好 等等。
希尔排序的稳定性
如序列: 21 25 排序后为:08 16
R[0]有两个作用:
其一: 进入查找循环之前,保存 R[i] 的副本,使之不至 于因记录的后移而丢失R[i]中的内容; 其二: 在 while 循环时,“监视”下标变量 j 是否越界, 一旦越界(j<0),R[0]自动控制while循环的结束, 从而 避免了在while 循环内的每一次都要检测 j 是否越界( 即 省略了循环条件j>=0)。 因此,把 R[0] 称为“监视哨”。
第七章 排 序
本章内容
排序的概念和有关知识
常用的几种排序方法的基本思想、排序过 程和算法实现 各种排序算法的时间复杂度分析
学生成绩表
学号 姓名 高数 英语 总分
005 010 002
018 004
Chen Lin Gao Hong Wang Na
ZhangYang Zhao Pen
84 69 90

计算机软件基础之数据结构-排序

计算机软件基础之数据结构-排序

26
快速排序的过程为:把待排序区间按照第一个元素 (即基准元素)的排序码分为左右两个子序列的过程叫做 一次划分。设待排序序列为R[left]~R[right],其中left为 下限,right为上限,left<right,R[left]为该序列的基准元 素,为了实现一次划分,令i,j的初值分别为left和right。在 划分过程中,首先让j从它的初值开始,依次向前取值,并 将每一元素R[j]的排序码同R[left]的排序码进行比较,直到 R[j]<R[left]时,交换R[j]与R[left]的值,使排序码相对较 小的元素交换到左子序列,然后让i从i+1开始,依次向后 取值,并使每一元素R[i]的排序码同R[j]的排序码(此时 R[j]为基准元素)进行比较,直到R[i]>R[j]时,交换R[i] 与R[j]的值,使排序码大的元素交换到后面子区间;再接 着让j从j-1开始,依次向前取值,重复上述过程,直到i等 于j,即指向同一位置为止,此位置就是基准元素最终被存 放的位置。此次划分得到的前后两个待排序的子序列分别 2013年6月28日星期五 为R[left]~R[i-1]和R[i+1]~R[right]。
2013年6月28日星期五
19
3、希尔排序的效率分析 虽然我们给出的算法是三层循环, 最外层循环为log2n数量级,中间的for循 环是n数量级的,内循环远远低于n数量 级,因为当分组较多时,组内元素较少; 此循环次数少;当分组较少时,组内元 素增多,但已接近有序,循环次数并不 增加。因此,希尔排序的时间复杂性在O (nlog2n)和O(n2 )之间,大致为O (n1. 3)。
也可以说,将一组记录按某排序码递增或递减排 列的过程,称为排序。
2013年6月28日星期五 6
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

第8章 排序 8.1 排序的基本概念 8.2 插入排序 8.3 选择排序 8.4 交换排序 本章主要知识点: ● 排序的基本概念和衡量排序算法优劣的标准,其中衡量标准有算法的时间复杂度、空间复杂度和稳定性 ● 直接插入排序,希尔排序 ● 直接选择排序,堆排序 ● 冒泡排序,快速排序 8.1排序的基本概念 1.排序是对数据元素序列建立某种有序排列的过程。 2.排序的目的:便于查找。 3.关键字是要排序的数据元素集合中的一个域,排序是以关键字为基准进行的。 关键字分主关键字和次关键字两种。对要排序的数据元素集合来说,如果关键字满足数据元素值不同时该关键字的值也一定不同,这样的关键字称为主关键字。不满足主关键字定义的关键字称为次关键字。 4.排序的种类:分为内部排序和外部排序两大类。 若待排序记录都在内存中,称为内部排序;若待排序记录一部分在内存,一部分在外存,则称为外部排序。 注:外部排序时,要将数据分批调入内存来排序,中间结果还要及时放入外 存,显然外部排序要复杂得多。 5.排序算法好坏的衡量标准: (1)时间复杂度—— 它主要是分析记录关键字的比较次数和记录的移动次数。 (2)空间复杂度——算法中使用的内存辅助空间的多少。 (3)稳定性——若两个记录A和B的关键字值相等,但排序后A、B的先后次序保持不变,则称这种排序算法是稳定的。 8.2 插入排序 插入排序的基本思想是:每步将一个待排序的对象,按其关键字大小,插入到前面已经排好序的一组对象的适当位置上,直到对象全部插入为止。 简言之,边插入边排序,保证子序列中随时都是排好序的。 常用的插入排序有:直接插入排序和希尔排序两种。 8.2.1 直接插入排序 1、其基本思想是: 顺序地把待排序的数据元素按其关键字值的大小插入到已排序数据元素子集合的适当位置。 例1:关键字序列T=(13,6,3,31,9,27,5,11), 请写出直接插入排序的中间过程序列。 初始关键字序列:【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】 注:方括号 [ ]中为已排序记录的关键字,下划横线的 关键字 表示它对应的记录后移一个位置。 2.直接插入排序算法 public static void insertSort(int[] a){ int i, j, temp; int n = a.Length; for(i = 0; i < n - 1; i ++){ temp = a[i + 1]; j = i; while(j > -1 && temp < a[j]){ a[j + 1] = a[j]; j --; } a[j + 1] = temp; } } 初始关键字序列:【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、直接插入排序算法分析 (1)时间效率:当数据有序时,执行效率最好,此时的时间复杂度为O(n);当数据基本反序时,执行效率最差,此时的时间复杂度为O(n2)。所以当数据越接近有序,直接插入排序算法的性能越好。 (2)空间效率:仅占用1个缓冲单元——O(1) (3)算法的稳定性:稳定 8.2.2 希尔(shell)排序 (又称缩小增量排序) 1、基本思想:把整个待排序的数据元素分成若干个小组,对同一小组内的数据元素用直接插入法排序;小组的个数逐次缩小,当完成了所有数据元素都在一个组内的排序后排序过程结束。 2、技巧:小组的构成不是简单地“逐段分割”,而是将相隔某个增量d的记录组成一个小组,让增量d逐趟缩短(例如依次取5,3,1),直到d=1为止。 3、优点:让关键字值小的元素能很快前移,且序列若基本有序时,再用直接插入排序处理,时间效率会高很多。 例2:设待排序的序列中有12个记录,它们的关键字序列 T=(65,34,25,87,12,38,56,46,14,77,92,23),请写出希尔排序的具体实现过程。 public static void shellSort(int[] a, int[] d, int numOfD){ int i, j, k, m, span; int temp; int n = a.Length; for(m = 0; m < numOfD; m ++){ //共numOfD次循环 span = d[m]; //取本次的增量值 for(k = 0; k < span; k ++){ //共span个小组 for(i = k; i < n-span; i = i + span){ temp = a[i+span]; j = i; while(j > -1 && temp < a[j]){ a[j + span] = a[j]; j = j - span; } a[j + span] = temp; } } } } 算法分析:开始时d 的值较大,子序列中的对象较少,排序速度较快;随着排序进展,d 值逐渐变小,子序列中对象个数逐渐变多,由于前面工作的基础,大多数记录已基本有序,所以排序速度仍然很快。 时间效率:O(n(log2n)2) 空间效率:O(1)——因为仅占用1个缓冲单元 算法的稳定性:不稳定 练习: 1. 欲将序列(Q, H, C, Y, P, A, M, S, R, D, F, X)中的关键码按字母升序重排,则初始d为4的希尔排序一趟的结果是? 答: 原始序列: Q, H, C, Y, P, A, M, S, R, D, F, X shell一趟后: P,A,C,S,Q,D,F,X,R,H,M,Y 2. 以关键字序列(256,301,751,129,937,863,742,694,076,438)为例,写出执行希尔排序(取d=5,3,1)算法的各趟排序结束时,关键字序列的状态。 解:原始序列: 256,301,751,129,937,863,742,694,076,438 希尔排序第一趟d=5 256 301 694 076 438 863 742 751 129 937 第二趟d=3 076 301 129 256 438 694 742 751 863 937 第三趟d=1 076 129 256 301 438 694 742 751 863 937 8.3 选择排序 选择排序的基本思想是:每次从待排序的数据元素集合中选取关键字最小(或最大)的数据元素放到数据元素集合的最前(或最后),数据元素集合不断缩小,当数据元素集合为空时选择排序结束。 常用的选择排序算法: (1)直接选择排序 (2)堆排序 8.3.1直接选择排序 1、其基本思想 每经过一趟比较就找出一个最小值,与待排序列最前面的位置互换即可。 (即从待排序的数据元素集合中选取关键字最小的数据元素并将它与原始数据元素集合中的第一个数据元素交换位置;然后从不包括第一个位置的数据元素集合中选取关键字最小的数据元素并将它与原始数据集合中的第二个数据元素交换位置;如此重复,直到数据元素集合中只剩一个数据元素为止。) 2、优缺点 优点:实现简单 缺点:每趟只能确定一个元素,表长为n时需要n-1趟 例3:关键字序列T= (21,25,49,25*,16,08),请给出直接选择排序的具体实现过程。 原始序列: 21,25,49,25*,16,08 第1趟 08,25,49,25*,16,21 第2趟 08,16, 49,25*,25,21 第3趟 08,16, 21,25*,25,49 第4趟 08,16, 21,25*,25,49 第5趟 08,16, 21,25*,25,49 public static void selectSort(int[] a){ int i, j, small; int temp; int n = a.Length; for(i = 0; i < n - 1; i ++){ small = i; //设第i个数据元素最小 for(j = i + 1; j < n; j ++) //寻找最小的数据元素 if(a[j] < a[small]) small = j; //记住最小元素的下标 if(small != i){ //当最小元素的下标不为i时交换位置 temp = a[i]; a[i] = a[small]; a[small] = temp; } } } 3、算法分析 时间效率: O(n2)——虽移动次数较少,但比较次数仍多。 空间效率:O(1)——没有附加单元(仅用到1个temp) 算法的稳定性:不稳定 4、稳定的直接选择排序算法 例:关键字序列T= (21,25,49,25*,16,08),请给出稳定的直接选择排序的具体实现过程。 原始序列: 21,25,49,25*,16,08 第1趟08, 21 , 25 , 49 , 25 *, 16 第2趟08,16, 21,25,49 ,25 * 第3趟08,16, 21,25,49 ,25 * 第4趟08,16, 21,25,49 ,25 * 第5趟08,16, 21,25,25 * ,49 public static void selectSort2(int [] a){ int i,j,small; int temp; int n = a.Length; for(i = 0; i < n-1; i++){ small = i; for(j = i+1; j < n; j++){ //寻找最小的数据元素 if(a[j] < a[small]) small = j; //记住最小元素的下标 } if(small != i){ temp = a[small]; for(j = small; j > i; j--) //把该区段尚未排序元素依次后移 a[j] = a[j-1]; a[i] = temp; //插入找出的最小元素 } } } 8.3.2 堆排序 1. 什么是堆? 2. 怎样建堆? 3. 怎样堆排序? 堆的定义:设有n个数据元素的序列 k0,k1,…,kn-1,当且仅当满足下述关系之一时,称之为堆。 解释:如果让满足以上条件的元素序列 (k0,k1,…,kn-1)顺次排成一棵完全二叉树,则此树的特点是: 树中所有结点的值均大于(或小于)其左右孩子,此树的根结点(即堆顶)必最大(或最小)。 例4:有序列T1=(08, 25, 49, 46, 58, 67)和序列T2=(91, 85, 76, 66, 58, 67, 55),判断它们是否 “堆”? 2. 怎样建堆? 步骤:从第一个非终端结点开始往前逐步调整,让每个双亲大于(或小于)子女,直到根结点为止。 终端结点(即叶子)没有任何子女,无需单独调整 例:关键字序列T= (21,25,49,25*,16,08),请建最大堆。 解:为便于理解,先将原始序列画成完全二叉树的形式: 这样可以很清晰地从(n-1-1)/2开始调整。

相关文档
最新文档