当前位置:   article > 正文

数据结构——堆排序_无序序列第一次处理堆顶记录

无序序列第一次处理堆顶记录

堆的实质:

任意非子叶结点均小于(大于)它的孩子结点的完全二叉树。

堆排序的思想:

每次构造一个堆,将堆的根节点添加到有序序列中。

其中,r1 为最大值

与最后一个元素 rn 交换

对无序序列进行堆调整

得到最大的值

继续进行交换,重复步骤,即可得到有序序列。

堆的定义

堆是具有下列性质的完全二叉树:

每个结点的值都小于或等于其左右孩子结点的值(称为小根堆) 或 每个结点的值都大于或等于其左

右孩子结点的值(称为大根堆)。

小根堆:

特点:

1、小根堆的根节点是所有节点的最小者。

2、较小的结点靠近根节点,但不绝对。

大根堆:

特点:

1、大根堆的根节点是所有节点的最大者。

2、较大的结点靠近根节点,但不绝对。

堆和序列的关系

采用顺序存储,编号后得

将堆用顺序存储结构来存储,则堆对应一组序列。

符合完全二叉树的性质:

堆调整

条件:左子树,右子树均为堆

从上向下进行处理大根

         

关键问题(1):由无序序列建立一个堆

假设:sift(r,k,end)函数为堆调整函数,其中k为要筛选节点的编号,end为堆中最后一个节点的编号。

注:最后一个结点的序号是n,则最后一个分支结点即为结点n的双亲,序号为n/2.

  1. for (k = n/2; k >= 1; k--)
  2. sift(r,k,n);

当k=4时,

K=3时,

K=2时,

K=1时,

经过sift函数的调用,完成大根堆。

  1. void sift(int r[], int k, int end)
  2. {
  3. int i = k, j = 2 * i;
  4. int m = 0;
  5. while (j <= end)
  6. {
  7. if (j < end && r[j] < r[j + 1])
  8. j++;
  9. if (r[i] < r[j])
  10. {
  11. m = r[i];
  12. r[i] = r[j];
  13. r[j] = m;
  14. }
  15. i = j;
  16. j = 2 * i;
  17. }
  18. }

关键问题(2)处理堆顶记录

解决方法:

第k次处理堆顶是将堆顶记录r[1]与序列中第n-k+1个记录r[n-k+1]交换。

关键问题(3)调整剩余记录,成为一个新堆

解决办法:

sift(r,1,n-k)

  1. void heapsort(int r[], int n)
  2. {
  3. for (int k = n / 2; k >= 1; k--)
  4. sift(r, k, n); // 初建堆
  5. for (k = 1; k < n; k++)
  6. {
  7. r[0] = r[1];
  8. r[1] = r[n - k + 1];
  9. r[n - k + 1] = r[0];
  10. sift(r, 1, n - k); // 重建堆
  11. }
  12. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家小花儿/article/detail/826559
推荐阅读
相关标签
  

闽ICP备14008679号