选择类排序包括:
(1) 简单选择排序
(2)树形选择排序
(3)堆排序
简单选择排序:
【算法思想】:在第 i 趟简单选择排序中,从第 i 个记录开始,通过 n - i 次关键字比较,从 n - i + 1 个记录中选出关键字最小的记录,并和第 i 个记录进行交换
时间复杂度:O(n^2)
1 //此函数中a[0]不用,即对 a[1] ~ a[length-1] 排序;
//如果对a[0]~a[length-1]排序,将 for 循环中的 i = 1 改为 i = 0 即可,注意输出
2 void select(int a[],int length){//length为数组的长度
3 int i,j; 4 int min;//记录最小值的位置
5
6 for(i = 1;i < length - 1;i++){ 7 min = i; 8 //选择最小的值
9 for(j = i + 1;j < length;j++){ 10 if(a[j] < a[min]) //更新最小值的坐标
11 min = j; 12 } 13 if(min != i){ 14 int temp; 15 temp = a[min]; 16 a[min] = a[i]; 17 a[i] = temp; 18 } 19 } 20 }
堆排序:
堆排序是威洛母斯在1964年提出的对树形选择排序的改进算法,其只需要一个记录大小的辅助空间,采用向量数组方式存储,采用完全二叉树的顺序结构的特征进行分析,而非采用树的存储结构。
从小到大排序采用大根(顶)堆:r[i].key >= r[2i].key && r[i].key >= r[2i+1].key (结点值大于等于其左子与右子)
从大到小排序采用小根(顶)堆:r[i].key <= r[2i].key && r[i].key<= r[2i+1].key (结点值小于等于其左子与右子)
【算法思想】把待排序的记录的关键字存放在数组 r[1...n] 中,将 r 看成一棵完全二叉树的顺序表示,每个结点表示一个记录,第一个记录 r[1] 作为二叉树的根,以下各记录 r[2] ~ r[n] 依次逐层从左到右顺序排列,任意结点 r[i] 的左孩子是 r[2i] ,右孩子是 r[2i+1],双亲是 r[i/2]。对这棵二叉树进行调整建堆。
时间复杂度:O(nlog2n)
说明:在c语言中,i/2 的含义是整除,不同于数学中的定义,即 3/2 = 1,有一个向下取整的意思
堆排序可分为2步(从小到大排序):
<1> 建初堆:建立一个大根堆
<2>重建堆:进行 n - 1 趟的交换(r[1] 与 堆尾进行交换)和建堆的过程
1 /*堆排序*/
2 /*建初堆:大根堆*/
3 void AdjustDown(int a[],int k,int len); 4 void BuildMaxHeap(int a[],int len){ 5 int i; 6 for(i = len/2;i > 0;i--){ 7 AdjustDown(a,i,len); 8 } 9 } 10 //调整堆
11 void AdjustDown(int a[],int k,int len){ 12 a[0] = a[k];//将第一个记录移出
13 int i; 14 for(i = 2*k;i <= len;i = 2*i){ 15 if(i < len && a[i] < a[i+1])//不能忘记i < len,否则会超出范围
16 i++;//取左右子中的最大值
17 if(a[0] >= a[i]) 18 break; 19 else{ 20 a[k] = a[i]; //将a[i]调整到其双亲结点上
21 k = i; //修改k值,以便继续向下筛选
22 } 23 } 24 a[k] = a[0]; 25 } 26
27 void HeapSort(int a[],int len){ 28 BuildMaxHeap(a,len); 29 int i; 30 int temp; 31 for(i = len;i > 1;i--){ 32 //第一个和堆尾进行交换
33 temp = a[1]; 34 a[1] = a[i]; 35 a[i] = temp; 36 //调整堆
37 AdjustDown(a,1,i-1); 38 } 39 }
图可参照:https://blog.csdn.net/u013384984/article/details/79496052
测试:
1 int main(){ 2 int a[11] = {-1,2,3,1,4,7,3,5,1,6,0}; 3 int b[11] = {-1,2,3,1,4,7,3,5,1,6,0}; 4 int i,j; 5 select(a,11); //没有用a[0],对后面的元素进行排序
6 HeapSort(b,10);//数组的最后一个下标,a[0]为辅助单元
7 for ( i = 1;i < 11;i++){ 8 printf("%d \t",a[i]); 9 } 10 printf("\n"); 11
12 for ( i = 1;i < 11;i++){ 13 printf("%d \t",b[i]); 14 } 15 printf("\n"); 16 }