堆-堆排序学习总结

1.堆是什么?
  堆是一种特殊的完全二叉树.
  其中, 堆又分为最大堆和最小堆.
  最大堆: 任一父节点的值都比左右节点的值大.
  最小堆: 任一父节点的值都比左右节点的值小.

2. 堆排序的过程:
A. 最小堆升序排序: (最大堆降序排序类似)
  建立最小堆->保存根节点的值(或输出)
  ->把最后一个节点的值保存到根节点
  ->堆长减 1->调整为最小堆.以此循环.

更好的方法:
 B. 最大堆升序排序:(最小堆降序排序类似)
   建立最大堆->保存根节点的值->交换根节点和最后一个节点的值
   -> 堆长度减1-> 调整.以此循环.

 A:
 void delete_root_and_sort(int *heap_array, int len)
{
     int temp_len = len;
     int temp = 0;
     int i = 0;

     for (i = 1; i < len + 1; i++)
     {
        temp = heap_array[1];
        heap_array[1] = heap_array[temp_len];
        temp_len--;
        siftdown(heap_array, 1, temp_len);
        printf("%d ", temp);
     }
     printf("\n");
}
B:
 void max_delete_root_and_sort(int *heap_array, int len)
{
     int temp_len = len;
     int temp = 0;
     int i = 0;

     for (i = 1; i < len + 1; i++)
     {
        temp = heap_array[1];
        heap_array[1] = heap_array[temp_len];
        heap_array[temp_len] = temp;
        temp_len--;
        max_siftdown(heap_array, 1, temp_len);
     }

     for (i = 1; i < len + 1; i++)
     {
          printf("%d ", heap_array[i]);
     }
     printf("\n");
}

向下调整:
  进行向下调整的时候, 先比较两次再进行一次交换每进行一次比较交换一次好.
  下面代码中的father = min; 这句十分关键.flag标志是为了看是否需要继续调整. 因为调整是从最后一个父节点开始, 是一个从下往上的过程(此处脑袋浮现完全二叉树) , 所以如果上层不需要调整, 下层也不再需要(因为已经调整过了).
代码如下:

static void siftdown(int *heap_array, int father, int len)
{
     int    left_child = 0;
     int    right_child = 0;
     int    min = 0;
     int    flag = 0;       //是否需要继续往下的标识, 为1不需要.

     while (father * 2 <= len && flag == 0)
     {
         left_child = father * 2;
         right_child = father * 2 + 1;

         if (left_child <= len)     //存在左节点
         {
             if (heap_array[left_child] < heap_array[father])
             {
    //              swap(heap_array, father, left_child);
                  min = left_child;
             }
             else
             {
                 min = father;
             }
         }

         if (right_child <= len)
         {
             if (heap_array[right_child] < heap_array[min])
             {
    //              swap(heap_array, father, right_child);
                  min = right_child;
             }
         }

         if (min != father)
         {
              swap(heap_array, father, min);
              father = min;                 //这句很重要, 相当于递归调用siftdown.
         }
         else
         {
              //因为是从下往上操作, 所以当前如果不需要位置改变的话,
              //也不需要往下测试, 因为, 下面是已经排序好的了.
              flag = 1;
         }
     }
}

注意: 把堆数据放在数组的第[1]位开始会更方便.

源码:
https://github.com/isshe/DataStructure-Algorithm/tree/master/Heap

                                        勿在浮沙筑高台.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值