小大根交替堆
来源:互联网 发布:淘宝自己开的店铺呢 编辑:程序博客网 时间:2024/06/13 11:24
基于论文“Min-Max Heaps and Generalized Priority Queues”
- 定义
- 抽象数据类型
- 源代码
- 截图
- 应用
定义
values stored at nodes on even (odd) levels are smaller than or equal to (respectively, greater than) values stored at their descendants.
抽象数据类型
template<class T>class min_max_heap{public: min_max_heap(int initialCapacity = 10);//默认参数为10 ~min_max_heap() { delete[] heap; }//析构函数 bool empty() const { return heapSize == 0; }//判断堆是否为空 int size() const {//返回堆的大小 return heapSize; } T* getHeap() const { return heap; } void initialize(T *theHeap,int theSize);//根据已知数组建堆 const T& getMax();//得到最大值 const T& getMin();//得到最小值 void insert(T&);//插入值 const T& popMin();//删除最小值 const T& popMax();//删除最大值 void output(ostream& out);//输出public: int heapSize;//堆大小 int arrayLength;//堆的最大值 T *heap;//堆数组};
源代码
template<class T>min_max_heap<T>::min_max_heap(int initialCapacity) {//构造函数 if (initialCapacity < 1) {//初始大小必须大于0 ostringstream s; s << "Error : Initial capacity = " << initialCapacity << " Must be > 0"; throw s.str(); } arrayLength = initialCapacity + 1;// heap = new T[arrayLength]; heapSize = 0;}int is_min_level(int i) {//返回下标为i的数据的层(大层还是小层) if ((int)(floor(log(i) / log(2))) % 2) { return 0; } else { return 1; }}template<class T>int index_min_child_grandchild(min_max_heap<T>* h ,int i) {//找出下标为i的结点的儿子和孙子中最小的值 int a = first_child(i); int b = second_child(i); int d = second_child(a); int c = first_child(a); int f = second_child(b); int e = first_child(b); int min_idx = -1; if (a <= h->heapSize) min_idx = a; if (b <= h->heapSize && h->heap[b] < h->heap[min_idx]) min_idx = b; if (c <= h->heapSize && h->heap[c] < h->heap[min_idx]) min_idx = c; if (d <= h->heapSize && h->heap[d] < h->heap[min_idx]) min_idx = d; if (e <= h->heapSize && h->heap[e] < h->heap[min_idx]) min_idx = e; if (f <= h->heapSize && h->heap[f] < h->heap[min_idx]) min_idx = f; return min_idx;}template<class T>int index_max_child_grandchild(min_max_heap<T>* h, int i) {//找出下标为i的结点的儿子和孙子中最小的值 int a = first_child(i); int b = second_child(i); int d = second_child(a); int c = first_child(a); int f = second_child(b); int e = first_child(b); int max_idx = -1; if (a <= h->heapSize) max_idx = a; if (b <= h->heapSize && h->heap[b] > h->heap[max_idx]) max_idx = b; if (c <= h->heapSize && h->heap[c] > h->heap[max_idx]) max_idx = c; if (d <= h->heapSize && h->heap[d] > h->heap[max_idx]) max_idx = d; if (e <= h->heapSize && h->heap[e] > h->heap[max_idx]) max_idx = e; if (f <= h->heapSize && h->heap[f] > h->heap[max_idx]) max_idx = f; return max_idx;}template<class T>void swap(min_max_heap<T>* h, int i, int m) {//交换堆中下标为i和m的数据 T temp = h->heap[i]; h->heap[i] = h->heap[m]; h->heap[m] = temp;if(flagPrint)cout << " heap[" << i << "]:" << h->heap[m] << "<-->" << "heap[" << m << "]:" << h->heap[i] << endl <<"h:\n"<< *h << endl;}/*小层下滤,先找到自己儿子和孙子中最小的值。如果该值为儿子,证明自己没有孙子,这时只需比较该最小值与自己,如果该最小值小,则与自己交换位置,下滤结束;否则不变化,下滤结束;如果该值为孙子,则比较该最小值与自己,如果该最小值大于自己,则证明以该元素为根节点的树的最小值就是该元素,下滤完成;否则如果该最小值小于自己,则进行交换位置,交换后判断自己与父亲结点的大小关系: 如果父亲节点(大层)小于自己,则交换位置,交换后只有该父亲节点元素位置不正确,所以对父亲节点元素重新进行下滤; 否则父亲节点大于自己,则对自己重新进行下滤操作。*/template<class T>void TrickleDownMin(min_max_heap<T>* h,int i) {//小层下滤(用于删除) int m = index_min_child_grandchild(h,i);//得到儿子和孙子中最小的值 if (m <= -1) return; if (m > second_child(i)) {//如果孙子最小 if (h->heap[m] < h->heap[i]) { swap(h, i, m); if (h->heap[m] > h->heap[parent(m)]) { swap(h, m, parent(m)); } TrickleDownMin(h, m); } } else {//如果儿子最小 if (h->heap[m] < h->heap[i]) { swap(h, i, m); } }}template<class T>void TrickleDownMax(min_max_heap<T>* h,int i) {//大层下滤(用于删除) int m = index_max_child_grandchild(h, i);//得到儿子和孙子最大值 if (m <= -1) { return; } if (m > second_child(i)) {//如果孙子最大 if (h->heap[m] > h->heap[i]) { swap(h, i, m); if (h->heap[m] < h->heap[parent(m)]) { swap(h, m, parent(m)); } TrickleDownMax(h, m); } } else {//如果儿子最大 if (h->heap[m] > h->heap[i]) { swap(h, i, m); } }}template<class T>void trickleDown(min_max_heap<T>* h,int i) {//下滤,用于删除//cout << "先判断是删除了最小元素,还是最大元素" << endl; if (is_min_level(i)) { TrickleDownMin(h, i); } else { TrickleDownMax(h, i); }}template<class T>void bubbleup_min(min_max_heap<T>* h, int i) {//小层上滤 int pp_i = parent(parent(i)); if (pp_i <= 0) return; if (h->heap[i]<h->heap[pp_i]) {//如果祖父比自己大,则交换 swap(h, i, pp_i); bubbleup_min(h, pp_i); }}template<class T>void bubbleup_max(min_max_heap<T>* h, int i) {//大层上滤 int pp_i = parent(parent(i)); if (pp_i <= 0) return; if (h->heap[i]>h->heap[pp_i]) {//如果祖父比自己小则交换 swap(h, i, pp_i); bubbleup_max(h, pp_i); }}template<class T>void BubbleUp(min_max_heap<T>* h, int i) {//上滤,可用于插入 int p_i = parent(i); if (p_i <= 0) return; if (is_min_level(i)) {//如果是小层,进行父亲节点与自己的值大小比较 if (h->heap[i] > h->heap[p_i]) {//若父节点小,则交换,并进行大层上滤 swap(h, i, p_i); bubbleup_max(h, p_i); } else {//如果父节点大则进行小层上滤 bubbleup_min(h, i); } } else {//否则是大层 if (h->heap[i] < h->heap[p_i]) {//若父亲节点大于自己,则交换,并进行小层上滤 swap(h, i, p_i); bubbleup_min(h, p_i); } else {//否则父亲节点小于自己,进行大层交换 bubbleup_max(h, i); } }}template<class T>void min_max_heap<T>::initialize(T *theHeap, int theSize) {//初始化堆 delete[] heap; heap = theHeap; heapSize = theSize; for (int root = heapSize / 2; root >= 1; root--) { trickleDown(this, root); }}template<class T>void min_max_heap<T>::insert(T& Element) {//插入if (flagPrint) { cout << "插入操作-插入"; cout << Element; cout << ":" << endl;} //如果堆满可增加数组的长度,此处扩展为原先的2倍; if (heapSize == arrayLength - 1) { changeArrayLength(heap, arrayLength, 2 * arrayLength); arrayLength *= 2; } int currentNode = ++heapSize; heap[currentNode] = Element;if(flagPrint)cout <<"h:\n"<<*this<<endl; BubbleUp(this, currentNode);}template<class T>const T& min_max_heap<T>::getMax() {//返回最大值 printf("得到最大值操作:"); if (heapSize > 2) {//比较heap[2]和heap[3] printf("%d\n", heap[2] < heap[3] ? heap[3] : heap[2]); return heap[2] < heap[3] ? heap[3] : heap[2]; } if (heapSize == 2) { printf("%d\n", heap[2]); return heap[2]; } if (heapSize == 1) { printf("%d\n", heap[1]); return heap[1]; } throw "错误:空堆不能得到最大值\n";}template<class T>const T& min_max_heap<T>::getMin() {//返回根节点(即第一个元素)即最小元素 if (heapSize > 0) {cout << "得到最小值操作:" <<heap[1] << endl; return heap[1]; } throw "错误:空堆不能得到最小值\n"; //printf("错误:空堆\n"); //return NULL;}template<class T>const T& min_max_heap<T>::popMin() {//删除最小值if (flagPrint)cout << "删除最小值操作" << endl; if (heapSize > 1) { T d = heap[1];//cout << "将根节点" << heap[1] << "(最小值)替换为最后一个元素" << heap[heapSize] << ",开始下滤:" << endl; heap[1] = heap[heapSize--];if(flagPrint)cout << "heap[1] = "<<heap[1]<< endl <<"h:\n"<<*this << endl; trickleDown(this, 1); return d; } if (heapSize == 1) {if (flagPrint)cout << "只有一个元素,故删除后堆为空" << endl; heapSize--; return heap[1]; } throw "错误:空堆不能删除最小值\n"; //printf("错误:空堆\n"); //return NULL;}template<class T>const T& min_max_heap<T>::popMax() {//删除最大值if (flagPrint)cout << "删除最大值操作" << endl; if (heapSize > 2) { int index = 2; if (heap[2] < heap[3]) index = 3; T d = heap[index]; heap[index] = heap[heapSize--];if (flagPrint)cout << "heap["<<index<<"] = " << heap[index] << endl <<"h:\n"<<*this << endl; trickleDown(this, index); return d; } if (heapSize == 2) {if (flagPrint)cout << "两个元素,返回heap[2]即可" << endl; heapSize--; return heap[2]; } if (heapSize == 1) {if (flagPrint)cout << "只有一个元素,故删除后堆为空" << endl; heapSize--; return heap[1]; } throw "错误:空堆不能得到最小值\n";}//template<class T>template<class T>void min_max_heap<T>::output(ostream& out) {//输出堆元素 T **heapTreeMatrix; if (heapSize == 0) throw "Error : empty heap not output!"; int level = 0; int high = (int)(floor(log(heapSize) / log(2)));//high从0层开始 int bottle_node_count_max = pow(2, high);//最下层最多可以拥有的结点数 heapTreeMatrix = new T*[high + 1]; for (int i = 0; i < high + 1; i++) { heapTreeMatrix[i] = new T[bottle_node_count_max * 2]; } T *t = new T(INF); for (int i = 0; i < high+1 ; i++) { for (int j = 0; j < bottle_node_count_max*2; j++) { heapTreeMatrix[i][j] = *t; } } int index = 1; while (level < high + 1) { int inscrease = bottle_node_count_max * 2 / pow(2, level); for (int j = inscrease/2 ; j < bottle_node_count_max * 2; j += inscrease) { if(index<=heapSize) heapTreeMatrix[level][j] = heap[index++]; } level++; } for (int i = 0; i < high + 1; i++) { for (int j = 0; j < bottle_node_count_max * 2; j++) { if (heapTreeMatrix[i][j] == *t) { printf(" "); } else { out << setw(4) << heapTreeMatrix[i][j]; } } printf("\n"); } for (int i = 0; i < high + 1; i++) { delete[] heapTreeMatrix[i]; } delete[] heapTreeMatrix;}template<class T>ostream& operator<<(ostream& out, min_max_heap<T>& x) {//<<运算符重载 x.output(out); out << endl; return out;}
测试代码
char choose;min_max_heap<int> h(10);int initSize = 0;//初始化数组元素个数int array[2000];//初始化数组 int main(){ while (1) { printf("****************************************************************************************\n"); printf("菜单 小大根交替堆实现双端优先队列\n"); printf("** u 建立小大根交替堆\n"); printf("** i 插入元素\n"); printf("** b 删除最大值\n"); printf("** s 删除最小值\n"); printf("** g 得到最大值\n"); printf("** h 得到最小值\n"); printf("** q 退出\n"); printf("****************************************************************************************\n"); cin >> choose; int a;//临时存放int值 char c;//临时存放char值 try{ switch (choose) { case 'u': printf("建立小大根交替堆:\n"); printf("请输入关键值:\n"); getchar(); flagPrint = false; while (1) { scanf("%d", &a); c = getchar(); //h.insert(a); array[++initSize] = a;//初始化数组 if (c == '\n') break; } h.initialize(array, initSize); cout << "建堆如下:"<<endl << h << endl; //printf("按f回到主菜单\n"); break; case 'i': printf("插入:"); scanf("%d", &a); flagPrint = true; h.insert(a); break; case 'b': flagPrint = true; a = h.popMax(); printf("删除元素为%d\n", a); break; case 's': flagPrint = true; a = h.popMin(); printf("删除元素为%d\n", a); break; case 'h': h.getMin(); break; case 'g': h.getMax(); break; case 'q': return 0; default: printf("输入有误,请重新输入\n"); break; } } catch (string s) { cout << s << endl; } catch (char* s) { cout << s << endl; } }return 0;}
测试截图
应用
可以用来实现双端优先队列Double_Ended_Priority_Queue,方便的得到最大最小值。
0 0
- 小大根交替堆
- 宝座交替
- 交替字符串
- 交替字符串
- 交替字符串
- 交替字符串
- 交替字符串
- 交替字符串
- 交替字符串
- 交替字符串
- 交替字符串
- 交替字符串
- 字符交替
- 交替字符串
- 交替执行
- 交替最小二乘法
- 交替输出
- 交替播放图片广告
- 什么是Just In Time编译器?
- 165.n1-viewIndicator实现tab
- js中几种实用的跨域方法详解
- “按需加载”的应用
- CentOS-6.4下安装hadoop2.7.3
- 小大根交替堆
- js继承的几种实现方式
- 如何判断脚本加载完成
- Oracle同义词创建及其作用
- Android-TabLayout使用小结
- Windows常用软件离线下载地址
- 设计模式(一)之单例模式
- C++ getline
- LeetCode 30. Substring with Concatenation of All Words