最小堆
来源:互联网 发布:淘宝最火的女装店铺 编辑:程序博客网 时间:2024/05/13 08:29
最大堆和最小堆是二叉堆的两种形式。
- 最大堆:根结点的键值是所有堆结点键值中最大者的堆。
- 最小堆:根结点的键值是所有堆结点键值中最小者的堆。
不失一般性,只讨论根结点为最小层的情况。
插入[编辑]
只需要将节点插在二叉树的最后一个叶子结点位置,然后比较它对它父亲节点的大小,如果大则停止;如果小则交换位置,然后对父亲节点递归该过程直至根节点。复杂度为O(log(n))。
一般来说,插入的位置可以不是最后一个叶子节点,可以作为任意中间节点的孩子节点插入,将这个叶子节点变为中间节点后,按上文所说的方法调整节点顺序以保证维持堆特性不变。
删除[编辑]
要从堆中删除一个节点,用最后一个节点替换掉根节点,然后调整节点顺序以维持堆特性。
堆定义文件:
- #ifndef MINHEAP_H
- #define MINHEAP_H
- #include <iostream>
- using std::cin;
- using std::cout;
- using std::endl;
- using std::ostream;
- template <typename T>
- class MinHeap
- {
- friend ostream& operator << (ostream& os,const MinHeap<T> &heap)
- {
- for(int i = 0; i < heap.currentSize; i++)
- {
- os << heap.heapArray[i] << "\t";
- }
- return os;
- }
- private:
- T *heapArray;//存放堆数据的数组
- int maxSize;//堆所能容纳的最大元素数目
- int currentSize;//当前堆中元素数目
- void swap(int posx,int posy)//辅助函数,交换位置x和y的元素
- {
- T temp = heapArray[posx];
- heapArray[posx] = heapArray[posy];
- heapArray[posy] = temp;
- }
- void siftDown(int left) //向下筛
- {
- int currentPos = left; // 标识父结点
- int childPos = leftChild (currentPos); // 标识关键值较小的子结点
- while (childPos < currentSize)
- { // 过筛
- if ((childPos < currentSize-1) && (heapArray[childPos] > heapArray[childPos + 1]))
- {
- childPos++; // j指向右子结点,也就是元素最小的子节点
- }
- if (heapArray[currentPos] > heapArray[childPos])
- {
- swap(currentPos,childPos);
- currentPos = childPos;
- childPos = leftChild(childPos); // 向下继续调整
- }
- else
- {
- break; // 调整到位
- }
- }
- }
- void siftUp(int currentPos) //向上调整
- {
- int parentPos = parent(currentPos);//父节点位置
- while(currentPos > 0)//调整到0号位置则应停止
- {
- if(heapArray[currentPos] < heapArray[parentPos])//向上调整
- {
- swap(currentPos,parentPos);
- currentPos = parentPos;
- parentPos = parent(currentPos);
- }
- else
- {
- break;//已经到位
- }
- }
- }
- void buildHeap()
- {
- for(int i = currentSize/2 - 1; i >= 0; i--)
- {
- siftDown(i);//反复调用筛选函数
- }
- }
- public:
- MinHeap(const int size) : maxSize(size)
- {
- if(size <= 0)
- {
- return;
- }
- heapArray = new T[maxSize];
- currentSize = 0;
- /*
- //此处进行堆元素的赋值工作
- heapArray[0] = 19; //亦可以用插入的办法构造
- heapArray[1] = 8;
- heapArray[2] = 35;
- heapArray[3] = 65;
- heapArray[4] = 40;
- heapArray[5] = 3;
- heapArray[6] = 7;
- heapArray[7] = 45;
- currentSize = 8;
- buildHeap();*/
- }
- ~MinHeap()
- {
- delete []heapArray;
- }
- bool isEmpty() const// 如果堆空,则返回真
- {
- return currentSize == 0;
- }
- bool isLeaf(int pos) const//是否叶子节点
- {
- return (pos >= currentSize/2) && (pos <= currentSize-1);
- }
- int leftChild(int pos) const//返回左孩子位置
- {
- return 2 * pos + 1;
- }
- int rightChild(int pos) const//返回右孩子位置
- {
- return 2 * pos + 2;
- }
- int parent(int pos) const//返回父节点位置
- {
- return (pos-1)/2;
- }
- bool insert(T &newNode)//向堆中插入新元素newNode
- {
- if(currentSize == maxSize)//堆空间已经满
- {
- return false;
- }
- else
- {
- heapArray[currentSize] = newNode;
- siftUp(currentSize);//向上调整
- currentSize++;
- return true;
- }
- }
- bool remove(int pos, T& node) // 删除给定下标的元素
- {
- if(pos < 0 || pos > currentSize - 1)
- {
- return false;
- }
- node = heapArray[pos];
- heapArray[pos] = heapArray[--currentSize];// 用最后的元素值替代删除位置的元素
- if(heapArray[pos] < heapArray[parent(pos)])// 当前元素小于父结点,需要上升调整
- {
- siftUp(pos);
- }
- else
- {
- siftDown(pos);//向下筛
- }
- return true;
- }
- bool removeMin(T& node) // 删除堆顶的元素
- {
- /*if(currentSize == 0)
- {
- cout << "堆为空,无法移除!" << endl;
- return false;
- }
- else
- {
- node = heapArray[0];
- swap(0,--currentSize);//交换堆顶和最后一个元素
- if(currentSize > 1)
- {
- siftDown(0);
- }
- return true;
- }*/
- return remove(0,node);
- }
- };
- #endif
测试代码:
- #include "MinHeap.h"
- int main()
- {
- MinHeap<int> minheap(8);
- cout << "初始化堆:" << minheap << endl;
- int Key[] = {19,8,35,65,40,3,7,45} ;
- cout << "建堆前:" << endl;
- for(int i = 0;i < 8; i++)
- {
- minheap.insert(Key[i]);
- cout<< Key[i] << "\t";
- }
- cout << endl;
- cout << "建堆后:" << endl;
- cout << minheap << endl;
- int elem;
- cout<< "删除给定下标(3)的元素:" << endl;
- minheap.remove(3,elem);
- cout<< elem << " deleted." << endl;
- cout << "现在堆: " << endl;
- cout << minheap << endl;
- //插入45
- cout<< "插入45:" << endl;
- minheap.insert(elem);
- cout << "现在堆: " << endl;
- cout << minheap << endl;
- cout << "从堆顶删除最小值:" ;
- minheap.removeMin(elem);
- cout << elem << endl;
- cout << "现在堆: " << endl;
- cout << minheap << endl;
- system("pause");
- return 0;
- }
0 0
- 最小堆
- 最小堆
- 最小堆
- 最小堆
- 最小堆
- 最小堆
- 最小堆
- 最小堆
- 最小堆
- 最小堆
- 最小堆
- 最小堆
- 最小堆
- 最大堆/最小堆
- 最小堆。最大堆。
- 最大堆/最小堆
- 最大堆/最小堆
- 最大堆/最小堆
- mysql5.5 启动报错:File './mysql-bin.index' not found (Errcode: 13)
- 哈弗曼树
- 黑马程序员------------------多态
- Java基础19--System--Runtime--Math--Date--Calendar
- hdu 3681 二分枚举答案+dp判断答案
- 最小堆
- ZOJ-2207
- 二叉查找树
- 设计模式之生成器模式
- Javascript实现打印局部网页功能
- 尺取法+LA2678
- 利用Javascript实时显示系统时间
- 二叉树
- 动态链接库和静态链接库