定义:
二叉堆是一种特殊的堆,二叉堆是完全二叉树或者是近似完全二叉树。二叉堆满足堆特性:父節点的键值总是保持固定的序关系于任何一个子节点的键值,且每个節点的左子树和右子树都是一个二叉堆。
当父節点的键值总是大于或等于任何一个子节点的键值时为最大堆。 当父節点的键值总是小于或等于任何一个子节点的键值时为最小堆。
重点:
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;
}