二叉堆、堆排序

举报
用户已注销 发表于 2021/11/19 04:32:05 2021/11/19
【摘要】 目录 一,二叉堆 二,堆的调整 三,堆的创建 四,堆排序 五,堆元素更新 六,堆的插入 一,二叉堆 二叉堆是用数组实现的完全二叉树,也就是说物理结构是数组,逻辑结构是完全二叉树。 二叉堆分2种,最大堆和最小堆。 最大堆指的是,任何一个结点都比它的两个子结点(或1个或0个)要大,最小堆同理。 本文以最大堆为例进行展...

目录

一,二叉堆

二,堆的调整

三,堆的创建

四,堆排序

五,堆元素更新

六,堆的插入


一,二叉堆

二叉堆是用数组实现的完全二叉树,也就是说物理结构是数组,逻辑结构是完全二叉树。

二叉堆分2种,最大堆和最小堆。

最大堆指的是,任何一个结点都比它的两个子结点(或1个或0个)要大,最小堆同理。

本文以最大堆为例进行展示。

 

二,堆的调整

堆的调整指的是,给出一个完全二叉树,除了根结点之外,左子树是二叉堆,右子树是二叉堆,现在要调整元素位置,让整个树成为二叉堆。

其实就是把堆顶元素不停的往下塞,塞到合适的位置就停止了。

实现代码:


  
  1. template<typename T>
  2. bool cmp(T a, T b)
  3. {
  4. return a < b; //最大堆
  5. }
  6. template<typename T>
  7. void exchange(T* a, T* b)
  8. {
  9. T tmp = *a;
  10. *a = *b;
  11. *b = tmp;
  12. }
  13. int LeftChild(int id)
  14. {
  15. return id * 2;
  16. }
  17. int RightChild(int id)
  18. {
  19. return id * 2 + 1;
  20. }
  21. int Parent(int id)
  22. {
  23. return id/2;
  24. }
  25. template<typename T>
  26. void AdjustHeap(T* arr, int rootId, int size)
  27. {
  28. int largest = rootId, left = LeftChild(rootId), right = RightChild(rootId);
  29. if (left < size && cmp(arr[largest], arr[left]))largest = left;
  30. if (right < size && cmp(arr[largest], arr[right]))largest = right;
  31. if (largest == rootId)return;
  32. exchange(arr + rootId, arr + largest);
  33. AdjustHeap(arr, largest, size);
  34. }

时间复杂度:O(h),其中h是二叉堆的高度,h=Θ(log n),其中n=size,表示所有结点数目

 

三,堆的创建

给出一个数组,现在要交换元素位置,使得它变成一颗二叉堆。

实现代码:


  
  1. template<typename T>
  2. void InitHeap(T* arr, int size)
  3. {
  4. for (int i = size / 2; i >= 0; i--)AdjustHeap(arr, i, size);
  5. }

原理:因为是完全二叉树,所以最后一层的结点数目小于总数的一半,也就是说,从size/2到0覆盖了除掉最后一层之外的所有结点。

时间复杂度:Θ(n),其中n=size,表示所有结点数目

 

四,堆排序

算法思路:

先构建二叉堆,于是数组第一个元素就是最大元素,把它和最后一个元素交换,

对于剩下的n-1个元素,直接调用AdjustHeap即可再次变成堆,于是得到了这n-1个元素里面的最大值,

依次类推,最后就变成增序的数组了。


  
  1. template<typename T>
  2. void HeapSort(T* arr, int size)
  3. {
  4. InitHeap(arr, size);
  5. for (int i = size - 1; i > 0; i--) {
  6. exchange(arr + i, arr);
  7. AdjustHeap(arr, 0, i);
  8. }
  9. }

时间复杂度:O(n log n)

 

五,堆元素更新


  
  1. template<typename T>
  2. void HeapIncrese(T* arr, int size, int id, T newValue)
  3. {
  4. arr[id] = newValue;
  5. while (id > 0 && cmp(arr[Parent(id)], arr[id])) {
  6. exchange(arr + id, arr + Parent(id));
  7. id = Parent(id);
  8. }
  9. }
  10. template<typename T>
  11. void HeapDecrese(T* arr, int size, int id, T newValue)
  12. {
  13. arr[id] = newValue;
  14. AdjustHeap(arr, id, size);
  15. }
  16. template<typename T>
  17. void HeapChange(T* arr, int size, int id, T newValue)
  18. {
  19. if (cmp(arr[id], newValue))HeapIncrese(arr, size, id, newValue);
  20. else HeapDecrese(arr, size, id, newValue);
  21. }

 

六,堆的插入


  
  1. template<typename T>
  2. void HeapInsert(T* arr, int &size,T value)
  3. {
  4. HeapIncrese(arr,size+1,size,value);
  5. size++;
  6. }

 

文章来源: blog.csdn.net,作者:csuzhucong,版权归原作者所有,如需转载,请联系作者。

原文链接:blog.csdn.net/nameofcsdn/article/details/113484808

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。