排序算法-选择类排序
来源:互联网 发布:手机迅雷提示无网络 编辑:程序博客网 时间:2024/05/21 01:55
选择排序的算法思想:
重待排序的元素序列中选择最小(最大)的元素,将其放入在已排序序列的最前(最末),其余的元素构成新的待排序列。依次类推,直到待排序元素序列中没有待排元素。选择排序主要有两种:简单选择排序和堆排序。接下来我们来分别介绍一下这两种排序算法。
一、选择排序
算法思想:
简单选择排序是一种简单的选择类排序算法,它是通过依次找到待排序列中最小的数据元素,并将其放在序列的最前面,从而使待排序元素变成有序序列。它的基本思想描述如下:假设待排序的元素序列有n个元素,在第一趟排序过程中,从n个元素序列中选择最小的元素,并将其放在元素序列的最前面即第一个位置。第二趟排序过程中,从剩余的n-1个元素中,选择最小的元素,将其放在第二个位置。依次类推,直到没有带比较的元素,简单选择排序算法结束。例如,给定一个待排序序列:55 33 22 66 44 过程如下:第一个元素和其后的4个元素依次比较,55>33,33较小元素,33>22,22较小元素,22<66,22<44,较小元素任为22,最后将22与第一个元素交换,第一趟排完:22 33 55 66 44。33分别与55、66、44比较,33最小不用交换,第二趟排完:22 33 55 66 44,依次类推,第三趟排完:22 33 44 66 55,第四趟排完:22 33 44 55 66,前4个元素全部有序,第5个元素是最大的元素,排在第五个位置上自然也是有序,排序结束。
示例:65 32 71 28 83 7 53 49
第一趟:{7} 32 71 28 83 65 53 49
第二趟:{7 28} 71 32 83 65 53 49
第三趟:{7 28 32} 71 83 65 53 49
第四趟:{7 28 32 49} 83 65 53 71
第五趟:{7 28 32 49 53} 65 83 71
第六趟:{7 28 32 49 53 65} 83 71
第七趟:{7 28 32 49 53 65 71} 83
选择排序算法的实现:
void SelectSort(int a[],int n){ /*选择排序*/ int i,j,k,t; /*将i个元素和i+1...n个元素比较,将最小元素放在i个位置上*/ for(i=0;i<n-1;i++){ j=i; for(k=i+1;k<n;k++){/*序号最小的元素为j*/ if(a[k]<a[j]) j=k; } /*如果i不等于j,则需要交换a[i]和a[j]*/ if(j!=i) { t=a[i];a[i]=a[j];a[j]=t; } } }
主函数:
#include<stdio.h>void SelectSort(int a[],int n);/*简单选择排序*/ void DispArray(int a[],int n);/*输出数组序列*/void HeapSort(int a[],int n);/*堆排序*/int main(){ int a[]={65,32,71,28,83,7,53,49}; int n=8; SelectSort(a,n); //HeapSort(a,n); DispArray(a,n); return 0;}
输出数组函数:
void DispArray(int a[],int n){ int i; for(i=0;i<n;i++) printf("%d ",a[i]); printf("\n");}
主要用途:
简单选择排序算法实现简单,适用于待排序元素较少且对时间要求不高的场合。
稳定性与复杂度:
简单选择排序不是一种稳定的排序算法。在最好的情况下,待排序元素序列暗中非递减排列,则不需要移动元素。在最坏的情况下,待排序按照非递增排列,每一趟排序都需要移动元素,移动次数为3(n-1)。在任何情况下,简单选择排序算法都需要n*(n-1)/2次比较,总上所述,简单选择排序算法时间复杂度为O(n2)。空间复杂度为O(1)。
二、堆排序
堆排序也是属于选择类排序,它是简单选择排序算法的改进。堆排序利用二叉树的性质对元素进行排序,将完全二叉树从上到下、从左到右依次编号,如果每一个双亲节点元素值大于(小)等于该孩子节点的元素值,则根据编号构成的元素序列就是一个大(小)顶堆。
算法思想:
假设一个大顶堆中有n个元素,如果将堆中的根节点元素输出之后,再将剩下n-1个元素重新建立成一个新堆,并将根节点元素输出,然后将剩下的n-2个元素重新建立成堆,重复上述过程,知道堆中没有元素为止。输出的元素就是一个有序序列,这样的排序方法称为堆。
1、创建堆
假设待排序元素有n个 ,依次放在数组a中,第1个元素的关键字a[1]表示二叉树的根节点,剩下的元素a[2...n]依次与完全二叉树中的编号一一对应。例如,a[1]的左孩子节点元素放在a[2]中,右孩子节点元素放在a[3]中,a[i]的左孩子放在a[2*i]中,右孩子放在a[2*i+1]中。如果是大顶堆,则有a[i]>=a[2*i]且a[i]>=a[2*i+1] (i=1,2,...|n/2|向下取整)。建立大顶堆的算法思想:从位于元素序列中最后一个非叶子结点(第|n/2|元素)开始,逐层比较调整元素的位置使其满足a[i]>=a[2*i]且a[i]>=a[2*i+1] ,直至根节点为止。假设当前节点序号为i,则当前元素为a[i],其左孩子为a[2*i]右孩子a[2*i+1]。将左孩子为a[2*i]右孩子a[2*i+1]与a[i]比较,如果孩子节点元素值大于当前节点值,则交换两者;否则不交换。逐层向上执行此操作,直至根节点,这样就建立大顶堆。
i: 1 2 3 4 5 6 7 8
a[i]: 27 58 42 53 42 69 50 62
(1)初始状态
(2)从第4个元素开始,53<62,交换两个节点元素。
(3)比较第3个元素与其子树节点,因为69>50且42<69,所以交换42和69。
(4)比较第2个元素与其子树节点,因为62>42且62<58,所以交换58和62。
(5)比较第1个元素与其子树节点,因为69>62且27<69,所以交换27和69。
(6)比较第3个元素与其子树节点,因为50>42且27<50,所以交换27和50。
void CreateHeap(int a[],int n){ /*建立大顶堆*/ int i; for(i=n/2-1;i>=0;i--)/*从n/2-1开始建立*/ AdjustHeap(a,i,n-1);}
2、调整堆
调整堆算法描述:输出堆顶元素可以将堆顶元素放在堆的最后面,即将第1个元素与最后一个元素交换,则需要调整的元素序列就是a[1...n-1]。从根节点开始,如果其左、右节点元素值大于根节点元素值,选择较大的一个进行交换,也就是说如果a[2]>a[3],则将a[1]与a[2]惊喜交换,否则不交换。如果a[3]>a[2],则将a[1]与a[3]惊喜交换,否则不交换。逐层重复执行此操作,直至叶子节点,就完成了堆的调整,构成了一个新堆。
void AdjustHeap(int a[],int s,int m){ /*调整a[s...m],使其成为一个大顶堆*/ int t,j; t=a[s]; /*将根节点暂时保存在t中*/ for(j=2*s+1;j<=m;j*=2+1){ if(j<m&&a[j]<a[j+1])/*沿关键字较大的孩子节点向下筛选*/ j++; /*j为关键字较大的节点的下标*/ if(t>a[j]) break; a[s]=a[j]; s=j; } a[s]=t;/*将根节点插入到正确的位置*/ }
堆排序:
void HeapSort(int a[],int n){ /*利用堆排序算法对数组a中的元素进行排序*/ int t,i; CreateHeap(a,n); for(i=n-1;i>0;i--){ /*将堆顶元素与最后一个元素交换,从新调整堆*/ t=a[0]; a[0]=a[i]; a[i]=t; AdjustHeap(a,0,i-1);/*将a[0...i-1]调整为大顶堆*/ } }
主要用途:
堆排序算法实现比较复杂,它主要适用于大规模的数据排序,例如,如果需要在10万个数据元素找出前10个最小元素或最大元素,则适用堆排序算法效率最高。
稳定性和复杂度:
堆排序是不稳定排序算法。堆排序的时间耗费主要是在建立堆和调整堆时。一个深度h,元素个数为n的堆,其调整算法的比较次数最多是2(h-1)次,建立一个堆最多比较次数4n。一个完整的堆排序过程总共比较次数少于2nlog2n,依次堆排序平均时间复杂度和最坏时间复杂度都是O(nlog2n)。堆排序空间复杂度为O(1)。
- 排序算法-选择类排序
- 排序算法-选择排序
- 排序算法-选择排序
- 排序算法--选择排序
- 排序算法---选择排序
- 排序算法-选择排序
- 排序算法-选择排序
- 排序算法-选择排序
- 排序算法---选择排序
- 排序算法--选择排序
- 排序算法--选择排序
- 排序算法--选择排序
- 排序算法--选择排序
- 算法-排序-选择排序
- 排序算法:选择排序
- 排序算法---选择排序
- 排序算法:选择排序
- 排序算法--选择排序
- Struts2 拦截器Interceptor实现防止恶意登录(登录限制)
- Linux 快速删除大量小文件方法
- 深度学习Matlab工具箱代码详解
- oracle导出txt文本数据的2中方法
- 树
- 排序算法-选择类排序
- geoTools向shp文件中写数据
- Python中os与sys两模块的区别
- Ubuntu 安装 Python
- CentOS7下安装nginx与php
- Linux 中/var/spool/postfix/maildrop目录下堆积大量小文件
- 算法基础之字符串2
- 指令和控制器之间的交互
- nginx 重写规则,过滤某些url