最小堆与最大堆

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
                                        有问题发我邮箱:568551096@qq.com

                                                                          

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值