选择排序的基本思想是:每一趟在n-i+1(i=1,2,3,……n-1)个记录中选取关键字最小的记录作为有序序列中的第i个记录。
- 简单选择排序:
- 以n=5(【a1,a2,a3,a4,a5】)为例,将序列分为两部分,初始序列为【】+【a1,a2,a3,a4,a5】,选择排序每一趟排序的结果是:选择右边序列的最小元素加入左边序列的末尾。
- 代码:
#include<iostream> using namespace std; const int N=10; void SelectSort(int a[]) { cout<<"Before sort:"; for(int i=0;i<N;i++) cout<<a[i]<<" "; cout<<endl; for(int i=0;i<N;i++) { int pos=i; for(int j=i+1;j<N;j++) { if(a[j]<a[pos]) pos=j; } int temp=a[pos]; a[pos]=a[i]; a[i]=temp; } cout<<"after sort:"; for(int i=0;i<N;i++) { cout<<a[i]<<" "; } cout<<endl; return ; } int main() { int a[N]={6,5,2,1,8,1,12,34,23,10}; SelectSort(a); return 0; }
- 时间复杂度:O(N2)。无论记录的初始排列如何,所需进行的关键字之间的比较次数相同,故时间复杂度与初始排列无关,总是O(N2)。
- 效果图:
2.树形选择排序(Tree Selection Sort)(又称锦标赛排序Tournament Sort)
- 出发点:简单选择排序的主要操作是关键字之间的比较,从减少“比较”出发:显然,在n个关键字中选出最小值,至少需要n-1次比较,然而从剩余的n-1个关键字中选择次小值,却并非一定要n-2次比较(可利用前次比较所得信息减少以后各趟排序所需比较次数)。
- 基本思想:对n个记录的关键字进行两个一组的比较,然后再较小者之间继续两个一组比较……直至选出最小关键字。(构建出了一个完全二叉树,根节点最小)。选出次小关键字:将叶子节点中的最小关键字改为“最大值”,从该叶子节点开始,和其兄弟关键字比较,更新从叶子节点到根节点路径上个节点的关键值,则根节点为次小关键字。以此类推,,,直至排序完成。
- 时间复杂度:O(nlogn) 除最小关键字外,每个次小关键字需约log2n次比较
- 缺点:辅助空间大,和“最大值”进行多余比较
3. 堆排序(Heap Sort)
- 只需一个记录大小的辅助空间,每个待排序记录仅占一个存储空间
- 堆:是一个完全二叉树,可由一个数组实现。每个节点的值都大于等于(或小于等于)其左右孩子的值。
- 定义:输出堆顶最小值后,使得剩余元素的序列重建成一个堆,则得到n个元素中的次小值。如此反复执行,便得到一个有序序列,这个过程称为堆排序。
- 关键步骤:“筛选”(对于这样一个堆(:除堆顶元素外,均满足堆得定义,)将其自堆顶到叶子进行调整,从而变成一个新的堆)。
- 代码:
#include<iostream> using namespace std; const int N=11; void HeapAdjust(int a[],int s,int m) { int temp=a[s]; for(int i=2*s; i<=m; i=i*2) { if(i<m && a[i]<a[i+1]) i++; if(temp>a[i]) break; a[s]=a[i]; s=i; } a[s]=temp; } void HeapSort(int a[]) { cout<<"before:"; for(int i=1;i<N;i++) cout<<a[i]<<" "; cout<<endl; for(int i=N/2;i>0;i--) { HeapAdjust(a,i,N-1); } cout<<"heap:"; for(int i=1;i<N;i++) cout<<a[i]<<" "; cout<<endl; for(int i=N-1; i>1;i--) { int temp=a[1]; a[1]=a[i]; a[i]=temp; HeapAdjust(a,1,i-1); } cout<<"after heap sort:"; for(int i=1;i<N;i++) cout<<a[i]<<" "; cout<<endl; } int main() { int a[N]={0,6,5,2,1,8,1,12,34,23,10}; HeapSort(a); return 0; }
- 效果图:
- 时间复杂度:O(NlogN)
- 适用于n较大的文件,且最坏时间复杂度也为O(NlogN)