排序总结
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
内排序总结
排序的基本概念:
1.稳定的:如果待排序的表中,存在多个关键字相同的记录,经过
排序后这些具有相同关键字的记录之间的相对次序保持不变,则称这种排序方法是稳定的,反之,是不稳定的。
2.排序的分类:插入排序、选择排序、交换排序、归并排序和基数
排序。
一.插入排序(直接插入排序、希尔排序)
思想:每次将一个待排序的记录,按其关键字的大小插入到前
面已经排好序的字表中的适当位置,直到全部记录插入完为止。
1.直接插入排序(稳定的,复杂度O(n^2))
代码:
void InsertSort(TypeR[],int n){
//先假设第一个元素已经有序,从第二个开始依次和前面的元素比较,比前面的小则前移
inti,j;
Type temp;
for ( i = 1; i < n; i++)
{ temp=R[i];
j=i-1;//从右向左在有序表中找到R[i]的插入位置
while(j>=0 &&temp.key { R[j+1]=R[j];//将关键字大于R[i].key的记录后移 j--; } R[j+1]=temp;//在R[j+1]处插入R[i] } } 分析:初始表正序时,比较次数最小为n-1,总移动次数为2;初始表反序时,比较次数最大为n(n-1)/2,移动次数最大为(n-1)(n+4)/2.算法 的平均时间复杂度为Q(n^2),辅助空间复杂度为Q(1),是就地排序,是一种稳定的排序方法。 2.希尔排序 思想:实际上是一种分组插入方法。先取定一个小于n的整数d1作为第一个增量,把表的全部记录分成d1个组,所有距离为d1的倍数的记录放在同一组中,在各组内进行直接插入排序;然后,取第二个增量d2( 代码: void ShellSort(Type R[],int n) { int i,j,gap; Type temp; gap=n/2;//增量置初值 while(gap>0) { for(i=gap;i { temp=R[i]; j=i-gap; while(j>=0 &&temp.key { R[j+gap]=R[j]; j=j-gap; } R[j+gap]=temp; j=j-gap; } gap=gap/2;//减小增量 } } 分析:该算法的时间复杂度为O(nlog2 n),辅助空间复杂度为O(1),是一个就地排序,也是一种不稳定排序。 二.选择排序(直接选择排序和堆排序) 思想:每一趟从待排序的记录中选择关键字最小的记录,顺序放在一排好序的子表的最后,直到全部记录排序完毕。(适合于从大量的记录中选择一部分排序记录) 1.直接选择排序 思想:第i趟排序开始时,当前有序区和无序区分别为R[0…i-1]和R[i..n-1],该趟排序则是从当前无序区中选出关键字最小的记录R[k],将它与无序区的第一个记录R[i]互换,使R[0…i]和R[i+1…n-1]分别变为新的有序区和新的无序区。 代码: void SelectSort(Type R[],int n) { int i,j,k; Type temp; for(i=0;i { k=i; for(j=i+1;j if(R[j].key k=j;//k记下目前找到的最小关键字所在的位置 if(k!=i)//交换R[i]和R[k] { temp=R[i]; R[i]=R[k]; R[k]=temp; } } } 分析:无论表的初始状态为何,总的比较次数为n(n-1)/2,当初始表为正序时,移动次数为0,当初始表为反序时移动次数为3(n-1)。空间复杂度为O(1),为就地排序,是不稳定排序方法。 3.堆排序 简介:堆的定义:n个关键字序列k1…kn当且仅当满足以下条件时成为堆(1<=i<=n/2)(1)ki<=k2i且ki<=k2i+1(小根堆) 或(2)ki>=k2i 且ki>=k2i+1(大根堆)。 思想:堆排序是一种树形排序,在排序过程中,将R[1…n]看成是一棵完全二叉树的顺序存储结构,利用完全二叉树中双亲结点和孩子结点之间的内在关系,在当前无序区中选择关键字最大(或最小)的记录。 具体做法:把待排序的表的关键字存放在数组R[1..n](为了与二叉树的顺序存储结构一致,堆排序的数据序列的下标从1开始)中,将R 看做一棵二叉树,每个结点表示一个记录,原表的第一个记录R[1]作为二叉树的根,以下各记录依次逐层从左到右顺序排列,构成一棵完全二叉树,结点R[i]的左孩子是R[2i],右孩子是R[2i+1],双亲是R[i/2]。 采用筛选算法构建堆:假若完全二叉树的某一个结点i对于它的左子树、右子树已是堆,接下来需要将R[2i].key与R[2i+1].key之中的最大者与R[i].key比较,若R[i].key较小则交换,这有可能破坏下一级的堆。于是继续采用上述方法构造下一级的堆。直到完全二叉树中结点i构成堆为止。对于任意一棵完全二叉树,从i=n/2---1,反复利用上述思想建堆。大者“上浮”,小者被“筛选”下去。 代码:(调整堆) void sift(Type R[],int low,int high) {