1 堆
堆实际上是一个完全二叉树的层次序列,可以用数组表示(所以完全二叉树的下表公式也通用~)
建堆过程
n不必将值一个个地插入堆中,通过交换形成堆
n假设根的左、右子树都已是堆,并且根的元素名为R。这种情况下,有两种可能
筛选法 重要
template <class T>
void MinHeap<T>::SiftDown(int position)
{
int i=position;//标识父结点
int j=2*i+1;//标识关键值较小的子结点
T temp=heapArray[i];//保存父结点
//过筛
while(j<CurrentSize){
if((j<CurrentSize-1)&&
(heapArray[j]>heapArray[j+1]))
j++;//j指向数值较小的子结点
if(temp>heapArray[j]){
heapArray[i]=heapArray[j];
i=j;
j=2*j+1;//向下继续
}//end if
else break;
}//end if
heapArray[i]=temp;
}
建堆
n从堆的第一个分支结点heapArray[CurrentSize/2-1]开始,自底向上逐步把以各分支结点为根的子树调整成堆
template<class T>
void MinHeap<T>::BuildHeap()
{
//反复调用筛选函数
for (int i=CurrentSize/2-1; i>=0; i--)
SiftDown(i);
}
template<class T>
void MinHeap<T>::SiftUp(int position)
{//从position向上开始调整,使序列成为堆
int temppos=position;
T temp=heapArray[temppos];
while((temppos>0)&&(heapArray[parent(temppos)]>temp)) //请比较父子结点直接swap的方法,一次swap要进行三次赋值
{
heapArray[temppos]=heapArray[parent(temppos)];
temppos=parent(temppos);
}
heapArray[temppos]=temp;
}
template <class T>
bool MinHeap<T>::Insert(const T& newNode)
//向堆中插入新元素newNode
{
if(CurrentSize==MaxSize)//堆空间已经满
return FALSE;
heapArray[CurrentSize]=newNode;
SiftUp(CurrentSize);//向上调整
CurrentSize++;
}
移出最小值(优先队列出队)
n可以将堆中最后一个位置上的元素(数组中实际的最后一个元素)移到根的位置上,利用siftdown对堆重新调整
template<T>
T& MinHeap<T>::RemoveMin()
{//从堆顶删除最小值
if(CurrentSize==0)
{
//空堆
cout<<"Can't Delete";
exit(1);
}
else
{
//交换堆顶和最后一个元素
swap(0,--CurrentSize);
if(CurrentSize>1) // <=1就不要调整了
//从堆顶开始筛选
SiftDown(0);
return heapSize[CurrentSize];
}//end else
}
删除元素
template<class T>
bool MinHeap<T>::Remove(int pos, T& node)
{// 删除给定下标的元素
if((pos<0)||(pos>=CurrentSize))
return false;
//指定元素置于最后
T temp=heapArray[pos];
heapArray[pos]=heapArray[--CurrentSize];
SiftUp(pos);//上升筛
SiftDown(pos);//向下筛,不是SiftDown(0); 不是很懂这个!!!
node=temp;
return true;
}
建堆效率O(n)
插入结点、删除普通元素和删除最小元素的平均时间代价和最差时间代价都是O(logn)
堆是优先队列的一种自然的实现方法。