wang-编程日记三:
最小堆
最小堆的实质是把树储存在一个数组,在数组中,非叶结点的左子树在数组中的下标(设为x) = 该结点在数组中的下标 * 2 + 1;那么x + 1就是该结点的右子树.;
相反的如果某结点在数组中的下标为x,那么其父结点为 (x - 1)/2。
在一个单个的结点a和其左右子树b.c中,把其中最小的值赋给结点a,在这三个结点中a结点的值就变为最小的了。
从下到上或从上到下对每一个结点进行此操作就可以把根结点的值变为所有结点中的最小的,每个结点的值小于其左右子树的值,这就是最小堆.
最小堆代码:
#ifndef MINHEAP_H
#define MINHEAP_H
template<class T>
class MinHeap{
public:
MinHeap(int sz = 10); //建立一个空堆
MinHeap(T arr[], int n); //通过数组建立堆
~MinHeap() { delete[] heap; } //析构函数
bool Insert(T& x); //将x插入最小堆中
bool RemoveMin(T &x); //删除堆顶上的最小元素
bool IsEmpty()const{ return (currentSize == 0) ? true : false; } //判断堆是否为空
bool IsFull()const{ return (currentSize == maxHeapSize) ? true : false; }//判断堆是否满
void MakeEmpty(){ currentSize = 0; } //把堆置空
private:
T *heap; //存放最大堆的数组
int currentSize; //最小堆当前元素个数
int MinHeapSize; //最小堆最多允许元素个数
void siftDown(int start, int m); //从start到m下滑调整成为最小堆
void siftUp(int start); //从start到0上移调整成为最小堆
};
template<class T>
MinHeap<T>::MinHeap(int sz)
{
MinHeapSize = sz;
heap = new T[MinHeapSize];
currentSize = 0;
};
template<class T>
MinHeap<T>::MinHeap(T arr[], int n)
{
MinHeapSize = n;
heap = new T[MinHeapSize];
for (int i = 0; i < n; i++) //复制堆数组
heap[i] = arr[i];
currentSize = n; //找最初调整位置,最后分支节点
int currentPos = (currentSize - 2) / 2; //自底向上逐渐扩大形成堆
while (currentPos >= 0)
{
siftDown(currentPos, currentSize - 1); //局部自上向下下滑调整
currentPos--; //在向前换一个分支结点
};
};
template<class T>
void MinHeap<T>::siftDown(int start, int m)
{
int i = start, j = 2 * i + 1;
T temp = heap[i];
while (j <= m)
{
if (j<m&&heap[j] > heap[j + 1]) j++; //如果左子女比右子女小则把j指向右子女
if (temp <= heap[j]) break; //如果上面比下面大则无需交换推出循环
else { heap[i] = heap[j]; i = j; j = 2 * j + 1; } //否则交换位置并交换起始位置
};
heap[i] = temp;
};
template<class T>
void MinHeap<T>::siftUp(int start)
{
int j = start, i = (j - 1) / 2;
T temp = heap[j];
while (j > 0)
{
if (heap[i] <= temp)break;
else{ heap[j] = heap[i]; j = i; i = (i - 1) / 2; }
}
heap[j] = temp;
};
template<class T>
bool MinHeap<T>::Insert(T &x)
{
heap[currentSize] = x; //插入到最后
siftUp(currentSize); //向上调整
currentSize++; //堆计数+1
return true;
};
template<class T>
bool MinHeap<T>::RemoveMin(T &x)
{
if (currentSize == 0) return false;
x = heap[0]; //存储根数据
heap[0] = heap[currentSize - 1]; //把最后一个元素补到根结点
currentSize--; //堆计数-1
siftDown(0, currentSize - 1); //自下而上调整
return true;
};
#endif // MINHEAP_H
最大堆:
最大堆与最小堆类似,只是在判断结点(假设为x时)与其左右子树的值时把最大的值付给了x。
template<class T>
class MaxHeap{
public:
MaxHeap(int sz = 10); //建立一个空堆
MaxHeap(T arr[], int n); //通过数组建立堆
~MaxHeap() { delete[] heap; } //析构函数
bool Insert(T& x); //将x插入最大堆中
bool RemoveMax(T &x); //删除堆顶上的最大元素
bool IsEmpty()const{ return (currentSize == 0) ? true : false; } //判断堆是否为空
bool IsFull()const{ return (currentSize == maxHeapSize) ? true : false; }//判断堆是否满
void MakeEmpty(){ currentSize = 0; } //把堆置空
private:
T *heap; //存放最大堆的数组
int currentSize; //最大堆当前元素个数
int maxHeapSize; //最大堆最多允许元素个数
void siftDown(int start, int m); //从start到m下滑调整成为最大堆
void siftUp(int start); //从start到0下滑调整成为最大堆
};
template<class T>
MaxHeap<T>::MaxHeap(int sz)
{
maxHeapSize = sz;
heap = new T[maxHeapSize];
currentSize = 0;
};
template<class T>
MaxHeap<T>::MaxHeap(T arr[], int n)
{
naxHeapSize = n;
heap = new T[maxHeapSize];
for (int i = 0; i < n; i++) //复制堆数组
heap[i] = arr[i];
currentSize = n; //找最初调整位置,最后分支节点
int currentPos = (currentSize - 2) / 2; //自底向上逐渐扩大形成堆
while (currentPos >= 0)
{
siftDown(currentPos,currentSize - 1); //局部自上向下下滑调整
currentPos--; //在向前换一个分支结点
};
};
template<class T>
bool MaxHeap<T>::Insert(T &x)
{
heap[currentSize] = x; //插入到最后
siftUp(currentSize); //向上调整
currentSize++; //堆计数+1
return true;
};
template<class T>
bool MaxHeap<T>::RemoveMax(T &x)
{
if (currentSize == 0) return false;
x = heap[0]; //存储根数据
heap[0] = heap[currentSize - 1]; //把最后一个元素补到根结点
currentSize--; //堆计数-1
siftDown(0, currentSize - 1); //自下而上调整
return true;
};
template<class T>
void MaxHeap<T>::siftDown(int start, int m)
{
int i = start, j = 2 * i + 1;
T temp = heap[i];
while (j <= m)
{
if (j<m&&heap[j] <= heap[j + 1]) j++; //如果左子女比右子女小则把j指向右子女
if (temp >= heap[j]) break; //如果上面比下面大则无需交换推出循环
else { heap[i] = heap[j]; i = j; j = 2 * j + 1; } //否则交换位置并交换起始位置
};
heap[i] = temp;
};
template<class T>
void MaxHeap<T>::siftUp(int start)
{
int j = start, i = (j - 1) / 2;
T temp = heap[j];
while (j > 0)
{
if (heap[i] >= temp)break;
else{ heap[j] = heap[i]; j = i; i = (i - 1) / 2; }
}
heap[j] = temp;
};
----------wang
有问题发我邮箱:[email protected]