/************************************************************************
> File Name: BinaryHeap.cpp
> Author: wpf
> Mail: wpf9264@163.com
> Created Time: 2019年03月04日 星期一 16时42分52秒
************************************************************************/
#include<iostream>
#include <vector>
#include "dsexceptions.h"
using namespace std;
template<typename Comparable>
class BinaryHeap
{
private:
int currentSize;
vector<Comparable> array;
void buildHeap()
{
for(int i=currentSize/2; i>0; --i)
percolateDown(i);
}
void percolateDown(int hole)
{
int child;
Comparable tmp = std::move(array[hole]);//将要下滤的元素保存下来
for( ; hole*2 <= currentSize; hole = child)
{
//说明该节点有孩子
child = hole*2;
//找到儿子中的最小值,准备上移
if(child != currentSize && array[child+1] < array[child])
++child;
if(array[child] < tmp)
array[hole] = array[child];
else
break;
}
array[hole] = std::move(tmp);
}
public:
//capacity+1 是为了处理默认输入capacity=0时的情况
explicit BinaryHeap(int capacity = 100):array(capacity + 1),currentSize{0}
{ }
//这里要对item.size()进行格式转换,不然会警告narrowing conversion
explicit BinaryHeap(const vector<Comparable> & item):array(item.size()+10),currentSize{int(item.size())}
{
for(int i=0; i<item.size(); ++i)
array[i+1] = item[i];
buildHeap();
}
bool isEmpty()const
{ return currentSize==0; }
const Comparable & findMin()const
{
if(isEmpty())
throw UnderflowException{};
return array[1];
}
void insert(const Comparable & x)
{
//堆内部的数组不够用了,现在进行扩容
if(currentSize == array.size()-1)
array.resize(array.size()*2);
//建立一个空穴,并保存要插入的值
int hole = ++currentSize;
//下面这句也可以去掉,直接令array[0]=std::move(x)
Comparable copy = std::move(x); //这里为什么非要加一个copy呢,直接用x给array[0]赋值不就行了
//开始上滤
array[0] = std::move(copy);
for( ; x<array[hole/2]; hole/=2)
array[hole] = std::move(array[hole/2]);//父节点下移
array[hole] = std::move(array[0]);
}
void insert(Comparable && x)
{
//堆内部的数组不够用了,现在进行扩容
if(currentSize == array.size()-1)
array.resize(array.size()*2);
//建立一个空穴,并保存要插入的值
int hole = ++currentSize;
for( ;hole>1 && x<array[hole/2]; hole/=2)
array[hole] = std::move(array[hole/2]);//父节点下移
array[hole] = std::move(x);
}
void deleteMin()
{
if(isEmpty())
throw UnderflowException{};
array[1] = std::move(array[currentSize--]);
percolateDown(1);
}
//删除最小项,并将其放在minItem
void deleteMin(Comparable & minItem)
{
if(isEmpty())
throw UnderflowException{};
minItem = std::move(array[1]);
array[1] = std::move(array[currentSize--]);
percolateDown(1);
}
void makeEmpty()
{
currentSize= 0;
}
};
int main(int argc,char** argv)
{
BinaryHeap<int> v;
cout<<"isEmpty()= "<<v.isEmpty()<<endl;
v.insert(8);
v.insert(2);
v.insert(0);
v.insert(6);
v.insert(9);
v.insert(7);
v.insert(4);
v.insert(3);
cout<<"isEmpty()= "<<v.isEmpty()<<endl;
int a;
v.deleteMin(a);
cout<<"min(): "<<a<<endl;
v.deleteMin(a);
cout<<"min(): "<<a<<endl;
v.deleteMin(a);
cout<<"min(): "<<a<<endl;
v.makeEmpty();
cout<<"isEmpty()= "<<v.isEmpty()<<endl;
vector<int> dd{8,2,0,6,9,7,4,3};
BinaryHeap<int> t{dd};
cout<<"isEmpty()= "<<t.isEmpty()<<endl;
t.deleteMin(a);
cout<<"min(): "<<a<<endl;
t.deleteMin(a);
cout<<"min(): "<<a<<endl;
t.deleteMin(a);
cout<<"min(): "<<a<<endl;
t.makeEmpty();
cout<<"isEmpty()= "<<t.isEmpty()<<endl;
return 0;
}
以下为测试结果: