zoukankan      html  css  js  c++  java
  • 2.5堆(Heap)的定义和性质

    2.5.1堆的定义

    优先队列:特殊的“队列”,取出元素的顺序是依照元素的优先权(关键字)大小,而不是元素进入队列的先后顺序。
     
    堆的两个特性:
    • 结构性:用数组表示的完全二叉树
    • 有序性:任一结点的关键字是其子树所有节点的最大值最小值,最大堆(Max Heap),也称为大顶堆最小堆(Min Heap),也称为小顶堆

     2.5.2最大堆的创建(初始化空堆)

     1 //用数组存储一个堆
     2 typedef struct Heap* MaxHeap;
     3 struct Heap {
     4     int* Elements;//指向存储堆元素的数组
     5     int Size;//堆的当前元素个数
     6     int Capacity;//堆的最大容量
     7 };
     8 
     9 MaxHeap Create(int MaxSize) {
    10     MaxHeap H = (MaxHeap)malloc(sizeof(Heap));
    11     //从下标为1的位置开始存放
    12     H->Elements = (int*)malloc((MaxSize + 1) * sizeof(int));
    13     H->Size = 0;
    14     H->Capacity = MaxSize;
    15     H->Elements[0] = MaxData;//"哨兵",大于堆中所有元素的值
    16     return H;
    17 }

     2.5.3最大堆的插入

    将新增结点插入到从其父结点到根结点的有序序列中。

    注意,因为有哨兵的存在,所以当i=1的时候循环必然会停止执行

     1 //最大堆的插入 插入元素item
     2 void InsertMaxHeap(MaxHeap H, int item) {
     3     int i;
     4     if (H->Size == MaxSize) {
     5         cout << "最大堆已满";
     6         return;
     7     }
     8     else {
     9         i = ++H->Size;//i指向插入后堆中最后一个元素的位置
    10         for (; H->Elements[i / 2] < item; i /= 2) {//如果父结点更小
    11             H->Elements[i] = H->Elements[i / 2];//将父结点的值赋给当前结点
    12         }
    13         H->Elements[i] = item;
    14     }
    15 }

    2.5.4最大堆的删除

    取出根结点(最大值)元素,同时删除堆的一个结点(最后一个结点),等效于将最后一个结点的元素值替换最大的元素,然后调整成最大堆。

     1 //最大堆的删除
     2 int DeleteMaxHeap(MaxHeap H) {
     3     int parent, child;
     4     int MaxItem, tmp;
     5     if (Isempty(H)) {
     6         cout << "最大堆已空";
     7         return 0;
     8     }
     9     MaxItem = H->Elements[1];//第一个元素最大
    10     tmp = H->Elements[H->Size--];//记录最后一个元素
    11     for (parent = 1; parent * 2 <= H->Size; parent = child) {
    12         child = parent * 2;//左儿子
    13         //parent表示tmp当前的位置
    14         if (child != H->Size&&H->Elements[child] < H->Elements[child + 1])
    15             child++;
    16         if (tmp >= H->Elements[child])break;
    17         else
    18             H->Elements[parent] = H->Elements[child];
    19     }
    20     H->Elements[parent] = tmp;//返回的parent是tmp最终的位置
    21     return MaxItem;
    22 }

    2.5.5最大堆的建立

    建立最大堆:将已经存在的N个元素按最大堆的要求存放在一个一维数组中

    】:对于一组相同数据,插入建堆和调整建堆建出来的堆也许不一样

    【例题】:

     【分析】:

                    1
            2              3  
        4       5       6     7
      8   9  10  11  12

    建堆的话,主要考虑下沉的次数,以此定义高度。
    这样的话,8,9,10,11,12都是已经沉底的,要注意的是7也是在最底了。这些节点高度都是0。
    4,5,6都是最多可以沉1次的,高度为1.
    2,3最多能沉2次,高度为2.
    1可以沉3次,高度为3.
    1*3+2*2+3*1=3+4+3=10

    2.5.5.1方法一:插入建堆

     1 //插入建堆
     2 #include "pch.h"
     3 #include <iostream>
     4 #include <cstdlib>
     5 using namespace std;
     6 #define MaxSize 100
     7 #define MaxData 100
     8 
     9 //用数组存储一个堆
    10 typedef struct Heap* MaxHeap;
    11 struct Heap {
    12     int* Elements;//指向存储堆元素的数组
    13     int Size;//堆的当前元素个数
    14     int Capacity;//堆的最大容量
    15 };
    16 
    17 MaxHeap Create() {
    18     MaxHeap H = (MaxHeap)malloc(sizeof(Heap));
    19     //从下标为1的位置开始存放
    20     H->Elements = (int*)malloc((MaxSize + 1) * sizeof(int));
    21     H->Size = 0;
    22     H->Capacity = MaxSize;
    23     H->Elements[0] = MaxData;//"哨兵",大于堆中所有元素的值
    24     return H;
    25 }
    26 
    27 //最大堆的插入 插入元素item
    28 void InsertMaxHeap(MaxHeap H, int item) {
    29     int i;
    30     if (H->Size == MaxSize) {
    31         cout << "最大堆已满";
    32         return;
    33     }
    34     else {
    35         i = ++H->Size;//i指向插入后堆中最后一个元素的位置
    36         for (; H->Elements[i / 2] < item; i /= 2) {//如果父结点更小
    37             H->Elements[i] = H->Elements[i / 2];//将父结点的值赋给当前结点
    38         }
    39         H->Elements[i] = item;
    40     }
    41 }
    42 
    43 //遍历输出
    44 void HeapTraversal(MaxHeap H) {
    45     for (int i = 1; i <= H->Size; i++)
    46         cout << H->Elements[i] << " ";
    47 }
    48 
    49 int main() {
    50     MaxHeap H;
    51     H = Create();
    52     int n;
    53     cin >> n;
    54     for (int i = 0; i < n; i++) {
    55         int t;
    56         cin >> t;
    57         InsertMaxHeap(H,t);
    58     }
    59     HeapTraversal(H);
    60     return 0;
    61 }

    2.5.5.2方法二:调整建堆

    从最后一个有孩子结点的结点开始,其本身结点和孩子结点共同构成"子最大堆",借助前面删除的想法,对每个"子最大堆"排序,最后一层层的整合,最后最大堆建成。

     1 #include <iostream>
     2 #include <cstdlib>
     3 using namespace std;
     4 #define MaxSize 100
     5 #define MaxData 100
     6 
     7 //用数组存储一个堆
     8 typedef struct Heap* MaxHeap;
     9 struct Heap {
    10     int* Elements;//指向存储堆元素的数组
    11     int Size;//堆的当前元素个数
    12     int Capacity;//堆的最大容量
    13 };
    14 
    15 MaxHeap Create() {
    16     MaxHeap H = (MaxHeap)malloc(sizeof(Heap));
    17     //从下标为1的位置开始存放
    18     H->Elements = (int*)malloc((MaxSize + 1) * sizeof(int));
    19     H->Size = 0;
    20     H->Capacity = MaxSize;
    21     H->Elements[0] = MaxData;//"哨兵",大于堆中所有元素的值
    22     return H;
    23 }
    24 //将以i为根结点的子堆进行排序
    25 void SortHeap(MaxHeap H,int i) {
    26     int parent, child;
    27     int tmp = H->Elements[i];//保存将要进行调整的结点
    28     for (parent = i;parent*2<=H->Size; parent = child) {
    29         child = parent * 2;
    30         if (child != H->Size&&H->Elements[child] < H->Elements[child + 1])
    31             child++;//找到左右儿子中更大的一个
    32         if (tmp > H->Elements[child])break;
    33         else 
    34             H->Elements[parent] = H->Elements[child];
    35     }
    36     H->Elements[parent] = tmp;
    37 }
    38 
    39 //调整
    40 void adjust(MaxHeap H) {
    41     for (int i = H->Size / 2; i > 0; i--)
    42         SortHeap(H, i);
    43 }
    44 
    45 
    46 void HeapTraversal(MaxHeap H) {
    47     for (int i = 1; i <= H->Size; i++)
    48         cout << H->Elements[i] << " ";
    49 }
    50 
    51 int main() {
    52     MaxHeap H;
    53     H = Create();
    54     int n;
    55     cin >> n;
    56     for (int i = 0; i < n; i++) {
    57         cin >> H->Elements[i+1];
    58         H->Size++;
    59     }
    60     adjust(H);
    61     HeapTraversal(H);
    62     return 0;
    63 }
  • 相关阅读:
    RefineDet by hs
    RFCN by hs
    经典排序算法总结(二)by Rose
    Libra R-CNN——“平衡学习” by Rose
    经典排序算法总结(一)by Rose
    注意力机制在MDNet跟踪算法中的应用 by leona
    Deep Sort 多目标跟踪算法总结-by Wilson
    tf.truncated_normal_initializer
    tf.add_to_collection方法
    tf.trainable_variables方法
  • 原文地址:https://www.cnblogs.com/PennyXia/p/12628789.html
Copyright © 2011-2022 走看看