关于Heap学习记录

Posted itukas

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了关于Heap学习记录相关的知识,希望对你有一定的参考价值。

Heap分为MaxHeap和MinHeap

Heap均为完全二叉树

定义heap的结构

typedef struct{
    int *Elements;  //储存堆元素数据,假设储存数组
    int Size;       //堆当前元素个数
    int MaxSize;   //堆最大容量
}heap;

初始化heap的操作,以下为初始化一个Maxheap

Maxheap* Create(int n){
    Maxheap *h = new Maxheap;
    h->Elements = new int(n+1);   //开拓一个新数组,大小为n+1
    h->Size = 0;     //当前元素大小
    h->MaxSize = n;   //将最大元素初始化为n
    h->Elements[0] = MAXDATA; //MAXDATA为最大数字
    return h;
}

插入元素的算法伪代码:

InsertMaxHeap(Heap *&h, int x) {            //x为插入元素
    if(h堆满){
        输出错误信息
        return;
    }

    h->Size++;              //大小+1
    int i = h->Size;        //使i为当前堆的大小
    for (; h->Elements[i / 2] < x; i /= 2)      //若当前结点的父节点小于x,
        h->Elements[i] = h->Elements[i / 2];    //将当前节点父节点值赋给当前节点
    h->Elements[i] = x;                         //最后出了循环后将x赋给当前节点
}

图解:

技术图片

 

假设要插入的元素为20;

【6】为新加的节点下标,,开始i等于6;

根据循环h【3】=31,并不小于20,所以直接跳出循环并且h【6】=20

技术图片

 

 最终图


 

 若要插入元素 35,

同上标记i为6;

进入循环,看到h【3】=31小于35,所以h【6】=h【3】;

继续循环,h【3/2】即为h【1】,h【1】=44显然不小于35,所以跳出循环让h【3】=35

技术图片最终图

 



 

 

返回元素类型,并且删除这个元素,删除元素伪代码:

int delMaxHeap(Heap *&h){
    if(h为空){
          //输出错误信息
        return -1;   //返回一个不正常的值代表错误
    }
 int parent,child;                      //int一个父母和孩子的下标位置
    int MaxItem = h->Elements[1];             //要返回的值用MaxItem代替
    int temp = h->Elements[h->Size--];           //让堆的最后一个值作为temp
    for (parent = 1; parent * 2 <= h->Size; parent = child){   //parent从结点1开始  2*parent代表孩子
        child = 2 * parent;
        if((child != h->Size) //代表child并不是最后一个元素
                &&(h->Elements[child+1] > h->Elements[child]))
            child++;      //如果右孩子值大于左孩子,则让child指向右孩子
        if(temp >= h->Elements[child])   //如果temp大于当前节点的两个孩子,跳出循环
            break;
        else
            h->Elements[parent] = h->Elements[child];   //否则让当前节点等于孩子
    }
    h->Elements[parent] = temp;      //将temp赋给当前节点
    return MaxItem;
}

图解:原图:

技术图片

 

删除最大元素,即为h【1】:58;

首先将MaxItem=h【1】;

堆最后一个元素:31

temp=31;

 开始,此时h【1】=58,h【2】=44,h【3】=25,h【4】=35

 

 此时开始进入循环

parent=1;其左右孩子比较h【2】大于h【3】,child=2;

比较h【child】和temp,发现h【child】的44大于temp,所以h【1】=h【2】,

此时h【1】=44,h【2】=44,h【3】=25,h【4】=35

令parent=child,2,进行下一轮循环

h【parent】下一个孩子为35,child=4,有且仅有一个孩子,比较h【4】和temp,h【4】大,所以h【2】=h【4】

此时h【1】=44,h【2】=35,h【3】=25,h【4】=35

令parent=child,4

然后继续循环你会发现:parent*2=8,但这个堆size就只有4,所以不构成循环条件,跳出循环

并且令h【parent】=temp,31,

此时h【1】=44,h【2】=35,h【3】=25,h【4】=31,

技术图片

 

 完成。



以下是一个MaxHeap和MinHeap的排序程序:

【例】

技术图片
#include <iostream>
#include<fstream>
#define MAXDATA 114514      //极大值
#define MINDATA -114514     //极小值
using namespace std;
ofstream out("out.txt");
typedef struct HeapStruct{
    int *Elements;  //储存堆元素
    int Size;       //堆当前元素个数
    int Capacity;   //堆最大容量
}Heap;
Heap* CreateMaxheap(int Maxsize){
    Heap *h = new Heap;
    h->Elements = new int(Maxsize+1);
    h->Size = 0;
    h->Capacity = Maxsize;
    h->Elements[0] = MAXDATA;
    return h;
}
Heap* CreateMinheap(int Maxsize){
    Heap *h = new Heap;
    h->Elements = new int(Maxsize + 1);
    h->Size = 0;
    h->Capacity = Maxsize;
    h->Elements[0] = MINDATA;
    return h;
}

bool isFull(Heap *h){
    if (h->Size == h->Capacity)
        return true;
        else
            return false;
}
bool isEmpty(Heap *h){
    if(h->Size == 0)
        return true;
        else
            return false;
}

void InsertMaxHeap(Heap *&h, int x) {            //x为插入元素
    if(isFull(h)){
        out << "heap full!" << endl;
        return;
    }

    h->Size++;              //大小+1
    int i = h->Size;        //使i为当前堆的大小
    for (; h->Elements[i / 2] < x; i /= 2)      //若当前结点的父节点小于x,
        h->Elements[i] = h->Elements[i / 2];    //将当前节点父节点值赋给当前节点
    h->Elements[i] = x;                         //最后出了循环后将x赋给当前节点
}
void InsertMinHeap(Heap *&h,int x){
    if(isFull(h)){
        out << "is full!" << endl;
        return;
    }
    h->Size++;
    int i = h->Size;
    for (; h->Elements[i / 2] > x; i /= 2)
        h->Elements[i] = h->Elements[i / 2];
    h->Elements[i] = x;
}

int delMaxHeap(Heap *&h){
    int parent, child;
    if(isEmpty(h)){
        out << "is empty!" << endl;
        return -1;
    }
    int MaxItem = h->Elements[1];
    int temp = h->Elements[h->Size--];
    for (parent = 1; parent * 2 <= h->Size; parent = child){
        child = 2 * parent;
        if((child != h->Size)//代表child并不是最后一个元素
                &&(h->Elements[child+1] > h->Elements[child]))
            child++;
        if(temp >= h->Elements[child])
            break;
        else
            h->Elements[parent] = h->Elements[child];
    }
    h->Elements[parent] = temp;
    return MaxItem;
}
int delMinHeap(Heap *&h){
    if(isEmpty(h)){
        out << "isempty" << endl;
        return -1;
    }
    int parent, child;
    int MinItem = h->Elements[1];
    int temp = h->Elements[h->Size--];
    for (parent = 1; 2 * parent <= h->Size; parent = child){
        child = 2 * parent;
        if((child!=h->Size)
            &&(h->Elements[child]>h->Elements[child+1]))
            child++;
        if(temp<=h->Elements[child])
            break;
        else
            h->Elements[parent] = h->Elements[child];
    }
    h->Elements[parent] = temp;
    return MinItem;
}

void buildMaxHeap(Heap *&h, int x[], int n){
    for (int i = 0; i < n; i++)
        InsertMaxHeap(h, x[i]);
}
void buildMinHeap(Heap *&h, int x[], int n){
    for (int i = 0; i < n; i++)
        InsertMinHeap(h,x[i]);
}

void SortMaxHeap(Heap *&h){
    while(!isEmpty(h))
        out << delMaxHeap(h) << ",";
}
void SortMinHeap(Heap *&h){
    while(!isEmpty(h))
        out << delMinHeap(h) << ",";
}

int main(){
    Heap *h = CreateMaxheap(13);
    int data[] = {7, 8, 9, 21, 14, 56, 54, 13, 87, 41, 16, 15, 23};
    buildMaxHeap(h, data, 13);
    SortMaxHeap(h);
    out << endl;
    
    Heap *h2 = CreateMinheap(13);
    buildMinHeap(h2, data, 13);
    SortMinHeap(h2);
    out << endl;
    system("pause");
}
View Code

输出为

/*out.txt*/
87,56,54,41,23,21,16,15,14,13,9,8,7,
7,8,9,13,14,15,16,21,23,41,54,56,87,

 

以上是关于关于Heap学习记录的主要内容,如果未能解决你的问题,请参考以下文章

STL_算法_Heap算法(堆排)(精)

STL_算法_Heap算法(堆排)(精)

ElasticSearch学习问题记录——Invalid shift value in prefixCoded bytes (is encoded value really an INT?)(代码片段

学习jvm,关于MAT an internal error occurred during:"Parsing heap dump" from问题

how2heap学习

算法学习老算法,新姿势,STL——Heap