二叉堆

定义
二叉堆是一种特殊的堆,二叉堆是完全二叉树或者是近似完全二叉树。二叉堆满足堆特性:父節点的键值总是保持固定的序关系于任何一个子节点的键值,且每个節点的左子树和右子树都是一个二叉堆。

当父節点的键值总是大于或等于任何一个子节点的键值时为最大堆。 当父節点的键值总是小于或等于任何一个子节点的键值时为最小堆。

重点
1.存储方式,结点与其父节点 孩子节点的位置关系
二叉堆一般用数组来表示。如果根节点在数组中的位置是1,第n个位置的子节点分别在2n和 2n+1。因此,第1个位置的子节点在2和3,第2个位置的子节点在4和5。以此类推。这种基于1的数组存储方式便于寻找父节点和子节点。
如果存储数组的下标基于0,那么下标为i的节点的子节点是2i + 1与2i + 2;其父节点的下标是⌊(i − 1) ∕ 2⌋。

2.插入节点时的上浮操作
在数组的最末尾插入新节点。然后自下而上调整子节点与父节点,时间复杂度Olog(n);
3.删除节点时下沉操作
对于最大堆,删除根节点就是删除最大值;对于最小堆,是删除最小值。然后,把堆存储的最后那个节点移到填在根节点处。再从上而下调整父节点与它的子节点

4.将乱序数组快速整理为堆,,复杂度为O(N);

#include<vector>
#include<iostream>
#include<exception>
#include<string>
#include<algorithm>


using namespace std;

template <class T>
class BinaryHeap
{
public:
    BinaryHeap();
    BinaryHeap(const vector<T> &v);
    bool isEmpty() const{ return mSize == 0; }
    int size() const{ return mSize  ; }
    const T& findMin() const;

    void insert(const T& x);
    void deleteMin();
    void makeEmpty();

private:
    int mSize;
    vector<T> array;

    void buildHeap();
    void perColateDown(int hole);

};

template<class T>
BinaryHeap<T>::BinaryHeap() :array(12), mSize(0)
{

}

template<class T> 
BinaryHeap<T>::BinaryHeap(const vector<T> &v) :array(v.size() + 1), mSize(v.size())
{
    for (int i = 0; i < (int)v.size(); i++)
    {
        array[i + 1] = v[i];
    }
    buildHeap();
}

template<class T>
const T& BinaryHeap<T>::findMin() const
{
    if (isEmpty())
        throw string("error");

        return array[1];

}


template<class T>
void BinaryHeap<T>::insert(const T&x)
{
    if (mSize + 1 == array.size())
    {
        array.resize(2 * mSize + 1);
    }

    //结点上浮操作
    int position = ++mSize;
    array[0] = x;//把x放在位置0 作为哨兵

    while (x < array[position / 2])
    {
        array[position] = array[position / 2];
        position /= 2;
    }
    array[position] = x;
}

template<class T>
void BinaryHeap<T>::deleteMin()
{
    if (!isEmpty())
    {
        array[1] = array[mSize--];
        perColateDown(1);
    }
}

template<class T>
void BinaryHeap<T>::perColateDown(int position)
{
    //结点下沉操作 将位置为position的结点下沉
    int child = 0;
    T temp = array[position];

    for (; position * 2 <= mSize; position = child)
    {
        child = position * 2;
        if (child != mSize && array[child + 1] < array[child])
        {
            child++;
        }
        if (array[child] < temp)
        {
            array[position] = array[child];
        }
        else break;
    }

    array[position] = temp;
}

template<class T>
void BinaryHeap<T>::buildHeap()
{
    //对于所有非叶子结点以逆向层序调用perColateDown , 可保证当第i个结点被处理时,其
    //所有后裔均已经通过该算法处理过。因而思路非常简单
    for (int i = mSize / 2; i > 0; --i)
    {
        perColateDown(i);
    }
}
int main()
{

    vector<int> v = { 1, 4, 8, 9,1,1,8,7, 4, 3, 2, 4 };
    BinaryHeap<int> Bh;

    for_each(v.begin(), v.end(), [&](int a){Bh.insert(a); });

    while (!Bh.isEmpty())
    {
        cout << Bh.findMin() << endl;
        Bh.deleteMin();
    }
    system("pause");
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值