关于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"); }
输出为
/*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学习记录的主要内容,如果未能解决你的问题,请参考以下文章
ElasticSearch学习问题记录——Invalid shift value in prefixCoded bytes (is encoded value really an INT?)(代码片段
学习jvm,关于MAT an internal error occurred during:"Parsing heap dump" from问题