选择类排序 (简单选择排序,堆排序)— c语言实现


选择类排序包括:

  (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 }