目录
1 头文件
#include "Vector.h" //借助多重继承机制,基于向量
#include "PQ.h" //按照优先级队列ADT实现的
#define Parent(i) ( ( ( i ) - 1 ) >> 1 ) //PQ[i]的父节点(floor((i-1)/2),i无论正负)
#define LChild(i) ( 1 + ( ( i ) << 1 ) ) //PQ[i]的左孩子
#define RChild(i) ( ( 1 + ( i ) ) << 1 ) //PQ[i]的右孩子
#define InHeap(n, i) ( ( ( -1 ) < ( i ) ) && ( ( i ) < ( n ) ) ) //判断PQ[i]是否合法
#define LChildValid(n, i) InHeap( n, LChild( i ) ) //判断PQ[i]是否有一个(左)孩子
#define RChildValid(n, i) InHeap( n, RChild( i ) ) //判断PQ[i]是否有两个孩子
#define Bigger(PQ, i, j) ( lt( PQ[i], PQ[j] ) ? j : i ) //取大者(等时前者优先)
#define ProperParent(PQ, n, i) /*父子(至多)三者中的大者*/ \
( RChildValid(n, i) ? Bigger( PQ, Bigger( PQ, i, LChild(i) ), RChild(i) ) : \
( LChildValid(n, i) ? Bigger( PQ, i, LChild(i) ) : i \
) \
) //相等时父节点优先,如此可避免不必要的交换
template <typename T> void heapify(T* A, Rank n); //Floyd建堆算法
template <typename T> Rank percolateDown(T* A, Rank n, Rank i); //下滤
template <typename T> Rank percolateUp(T* A, Rank i); //上滤
template <typename T> struct PQ_ComplHeap : public PQ<T>, public Vector<T> { //完全二叉堆
friend class UniPrint; //演示输出使用,否则不必设置友类
PQ_ComplHeap() { } //默认构造
PQ_ComplHeap(T* A, Rank n) { this->copyFrom(A, 0, n); heapify(this->_elem, n); } //批量构造
void insert(T); //按照比较器确定的优先级次序,插入词条
T getMax(); //读取优先级最高的词条
T delMax(); //删除优先级最高的词条
}; //PQ_ComplHeap
2. 相关函数
2.1 建堆函数
//Floyd建堆算法,O(n)时间
template <typename T> void heapify(T* A, const Rank n) {
for (Rank i = n / 2 - 1; 0 <= i; i--) //自底而上,依次
{
percolateDown(A, n, i); //下滤各内部节点
/*DSA*///for ( int k = 0; k < n; k++ ) {
/*DSA*/// int kk = k; while ( i < kk ) kk = (kk - 1) / 2;
/*DSA*/// i == kk ? print(A[k]) : print(" " );
/*DSA*///}; printf("\n");
}
}
//暴力建堆,O (n^2)时间
template <typename T> void bheapify(T* A, const Rank n) {
for (Rank i = n / 2 - 1; 0 <= i; i--) //自底而上,依次
{
for (int k = 0; k < n; k++) {
int kk = k; while (i < kk) kk = (kk - 1) / 2;
i == kk ? std::cout << A[k] : std::cout << " ";
};
std::cout << std::endl;
}
}
2.2 删除函数
//删除非空完全二叉堆中优先级最高的词条
template <typename T> T PQ_ComplHeap<T>::delMax() {
T maxElem = this->_elem[0]; this->_elem[0] = this->_elem[--this->_size]; //摘除堆顶(首词条),代之以末词条
percolateDown(this->_elem, this->_size, 0); //对新堆顶实施下滤
return maxElem; //返回此前备份的最大词条
}
2.3 获取函数
//取优先级最高的词条
template <typename T> T PQ_ComplHeap<T>::getMax() { return this->_elem[0]; }
2.4 插入函数
//将词条插入完全二叉堆中
template <typename T> void PQ_ComplHeap<T>::insert(T e) {
Vector<T>::insert(e); //首先将新词条接至向量末尾
percolateUp(this->_elem, this->_size - 1); //再对该词条实施上滤调整
}
2.5 上滤函数
//对向量中的第i个词条实施上滤操作,i < _size
template <typename T> Rank percolateUp(T* A, Rank i) {
while (0 < i) { //在抵达堆顶之前,反复地
Rank j = Parent(i); //考查[i]之父亲[j]
if ( lt(A[i], A[j]) ) break; //一旦父子顺序,上滤旋即完成;否则
swap(A[i], A[j]); i = j; //父子换位,并继续考查上一层
} //while
return i; //返回上滤最终抵达的位置
}
2.6 下滤函数
//对向量前n个词条中的第i个实施下滤,i < n
template <typename T> Rank percolateDown(T* A, Rank n, Rank i) {
Rank j; //i及其(至多两个)孩子中,堪为父者
while (i != (j = ProperParent(A, n, i))) //只要i非j,则
{
swap(A[i], A[j]); i = j;
} //二者换位,并继续考查下降后的i
return i; //返回下滤抵达的位置(亦i亦j)
}
3. 完整代码
#include<iostream>
#include "PQ_ComplHeap.h"
#include "Dice.h"
using namespace std;
template <typename T> void testPQ_ComplHeap(int n) {
PQ_ComplHeap<int> pqch;
while (pqch.size() < 2 * n) {
// cout << endl;
switch (dice(3)) {
case 0: { //删除,成功率 <= 33.3%
if (pqch.size() < 1) break;//边界条件,删除的前提是堆中存在最少一个元素
cout << "删除:" << pqch.getMax() ;
int oldsize = pqch.size();
pqch.delMax();
int newsize = pqch.size();
if (oldsize > newsize) cout << "删除成功!" << endl;
else cout << "删除失败!" << endl;
break;
}
default : { //插入,成功率 <= 66.6%
T key = dice((T)n * 12);
cout << "插入:" << key << " ";
int oldsize = pqch.size();
pqch.insert(key);
int newsize = pqch.size();
if (newsize>oldsize) cout << "插入成功!" << endl;
else cout << "插入失败!" << endl;
break;
}
} //switch
} //whil
while (pqch.size() > 0) {
cout << "删除:" << pqch.getMax();
pqch.delMax();
if (pqch.size()) cout << "删除成功!" << endl;
else cout <<endl<< "已全部删除!" << endl;
}
}
int main() {
srand((unsigned int)time(NULL));
int i = rand() % 20;
testPQ_ComplHeap<int>(i);
//PQ_ComplHeap<int> pqch;
//pqch.insert(5);
//pqch.insert(10);
//pqch.insert(4);
//cout << pqch.getMax() << endl;
//pqch.delMax();
//cout << pqch.getMax() << endl;
//pqch.delMax();
//cout << pqch.getMax() << endl;
system("pause");
return 0;
}
4. 运行结果及截图
以上所有代码参考邓俊辉老师的《c++语言版数据结构》!