堆排序——C语言

概念:

堆是一种完全二叉树的数据结构。堆排序(Heapsort)是指利用堆这种数据结构所设计的一种排序算法。

性质

大顶堆:每个结点的值都大于或等于该结点的左右孩子的结点值;

小顶堆:每个结点的值都小于或等于该结点的左右孩子的结点值。

 将给给定无序列构造成一个大顶堆;

1、从最后一个非叶子结点开始调整,也就是下面的7;判断是否满足大顶堆的性质,满足则跳过,不满足则调整。从上往下,从左往右调整。

2、找到倒数第二非叶子结点,判断是否满足大顶堆性质,满足则跳过,很显然倒数第二个非叶子结点(也就是下面的22)满足则跳过,同理倒数第三过也是如此。判断下一个叶子结点8,不满足大顶堆性质,则需要和其左孩子结点进行交换。

3、第一遍调整完后,再回到最后一个非叶子结点进行判断,直到所有非叶子结点都满足大顶堆的性质才结束;

 

 将给给定无序列构造成一个小顶堆;

将堆顶元素与末尾元素进行交换,使末尾元素最大。然后继续调整堆,再将堆顶元素与末尾元素比较交换,得到第二大元素。如此反复进行交换、重建、交换。

1、从最后一个非叶子结点判断是否满足小顶堆性质,满足则只需要其叶子结点与堆顶元素进行比较交换,不需要调整;不满足需要调整;

2、倒数第二个非叶子结点不满足小顶堆性质,但因顶堆元素比它大则不调整;将顶堆元素末尾元素进行比较,大则交换,小则于其上一个元素比较,同理。这里17于3进行交换;

 3、因倒数第二个非叶子结点不满足小顶堆性质,所有将3和16进行交换后顶堆元素再进行比较交换;

4、顶堆结点不满足小顶堆性质,所有将3和7进行交换; 

 

5、 最终实现小顶堆排序

 

 heapsort.c

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 
  4 void swap(int *a, int *b)
  5 {
  6     int temp = *b;
  7     *b = *a;
  8     *a = temp;
  9 }
 10 
 11 void max_heapify(int arr[], int start, int end)
 12 {
 13 
 14     // 建立父节点指向和子节点指向
 15     int dad = start;
 16     int son = dad * 2 + 1;
 17     while (son <= end)
 18     {
 19             //若子节点指向在范围内才做比较
 20         if (son + 1 <= end && arr[son] < arr[son + 1])

 21            //先比较两个子结点大小,选择最大的
 22             son++;
 23         if (arr[dad] > arr[son])
 24             //如果父节点大于子结点代表调整完后,直接跳出函数
 25                 return;
 26         else
 27         {
 28                 //否则交换父子内容在继续子结点和孙节点比较
 29             swap(&arr[dad], &arr[son]);
 30             dad = son;
 31             son = dad * 2 + 1;
 32         }
 33     }
 34 }
 35 
 36 void heap_sort(int arr[], int len)
 37 {
 38     int i;
 39    //初始化,i从最后一个父节点开始调整
 40     for (i = len / 2 - 1; i >= 0; i--)
 41         max_heapify(arr, i, len - 1);
 42    //先将第一个元素和已安排好元素前一位做交换,再重新调整,直到排序>    完整
 43     for (i = len - 1; i > 0; i--)
 44     {
 45         swap(&arr[0], &arr[i]);
 46         max_heapify(arr, 0, i - 1);
 47     }
 48 }
 49 
 50 int main()
 51 {
 52     int arr[] = { 90,70,80,60,10,40,20,50,30};
 53     int len = (int) sizeof(arr) / sizeof(*arr);
 54     heap_sort(arr, len);
 55     int i;
 56     for (i = 0; i < len; i++)
 57         printf("%d ", arr[i]);
 58     printf("\n");
 59     return 0;
 60 }
 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值