目录
1 头文件
1.1 二叉树头文件
参考 C++ 数据结构学习 ---- 二叉树_孤城寻欢的博客-CSDN博客
1.2 左式堆头文件
#include "PQ.h" //引入优先级队列ADT
#include "BinTree.h" //引入二叉树节点模板类
//基于二叉树,以左式堆形式实现的PQ
template <typename T>class PQ_LeftHeap : public PQ<T>, public BinTree<T> {
friend class UniPrint; //演示输出使用,否则不必设置友类
public:
PQ_LeftHeap() { } //默认构造
PQ_LeftHeap(T* E, int n) //批量构造:可改进为Floyd建堆算法
{
for (int i = 0; i < n; i++) insert(E[i]);
}
PQ_LeftHeap(PQ_LeftHeap& A, PQ_LeftHeap& B) { //合并构造
this->_root = merge(A._root, B._root); this->_size = A._size + B._size;
A._root = B._root = NULL; A._size = B._size = 0;
}
void insert(T); //按照比较器确定的优先级次序插入元素
T getMax(); //取出优先级最高的元素
T delMax(); //删除优先级最高的元素
}; //PQ_LeftHeap
1.3 Dice头文件
#include <ctime>
#include <Stdlib.h>
static int dice(int range) { return rand() % range; } //取[0, range)中的随机整数
static int dice(int lo, int hi) { return lo + rand() % (hi - lo); } //取[lo, hi)中的随机整数
static float dice(float range) { return rand() % (1000 * (int)range) / (float)1000.; }
static double dice(double range) { return rand() % (1000 * (int)range) / (double)1000.; }
static char dice() { return (char)(32 + rand() % 96); }
2. 相关函数
2.1 插入函数
template <typename T> void PQ_LeftHeap<T>::insert(T e) {
this->_root = merge(this->_root, new BinNode<T>(e, NULL)); //将e封装为左式堆,与当前左式堆合并
this->_size++; //更新规模
}
2.2 删除函数
template <typename T> T PQ_LeftHeap<T>::delMax() {
BinNodePosi(T) lHeap = this->_root->lc; if (lHeap) lHeap->parent = NULL; //左子堆
BinNodePosi(T) rHeap = this->_root->rc; if (rHeap) rHeap->parent = NULL; //右子堆
T e = this->_root->data; delete this->_root; this->_size--; //删除根节点
this->_root = merge(lHeap, rHeap); //合并原左、右子堆
return e; //返回原根节点的数据项
}
2.3 获取函数
template <typename T> T PQ_LeftHeap<T>::getMax()
{
return this->_root->data;
} //按照此处约定,堆顶即优先级最高的词条
2.4 合并函数
//合并以a和b为根节点的两个左式堆
template <typename T> BinNodePosi(T) merge(BinNodePosi(T) a, BinNodePosi(T) b) {
if (!a) return b; //退化情况
if (!b) return a; //退化情况
if (lt(a->data, b->data)) swap(a, b); //确保a>=b
for (; a->rc; a = a->rc) //沿右侧链做二路归并,直至堆a->rc先于b变空
if (lt(a->rc->data, b->data)) //只有在a->rc < b时才需做实质的操作
{
b->parent = a; swap(a->rc, b);
} //接入b的根节点(及其左子堆)
(a->rc = b)->parent = a; //直接接入b的残余部分(必然非空)
for (; a; b = a, a = a->parent) { //从a出发沿右侧链逐层回溯(b == a->rc)
if (!a->lc || a->lc->npl < a->rc->npl) //若有必要
swap(a->lc, a->rc); //通过交换确保右子堆的npl不大
a->npl = a->rc ? a->rc->npl + 1 : 1; //更新npl
}
return b; //返回合并后的堆顶
} //本算法只实现结构上的合并,堆的规模须由上层调用者负责更新
//合并以a和b为根节点的两个左式堆
/*
template <typename T> BinNodePosi(T) merge(BinNodePosi(T) a, BinNodePosi(T) b) {
if (!a) return b; //退化情况
if (!b) return a; //退化情况
if (lt(a->data, b->data)) swap(a, b); //确保a>=b
(a->rc = merge(a->rc, b))->parent = a; //将a的右子堆,与b合并
if (!a->lc || a->lc->npl < a->rc->npl) //若有必要
swap(a->lc, a->rc); //交换a的左、右子堆,以确保右子堆的npl不大
a->npl = a->rc ? a->rc->npl + 1 : 1; //更新a的npl
return a; //返回合并后的堆顶
} //本算法只实现结构上的合并,堆的规模须由上层调用者负责更新
*/
3. 完整代码
#include<iostream>
#include "Dice.h"
#include "PQ_LeftHeap.h"
using namespace std;
template <typename T> void testPQ_LeftHeap(int n) {
PQ_LeftHeap<int> pqlh;
while (pqlh.size() < 2 * n) {
// cout << endl;
switch (dice(3)) {
case 0: { //删除,成功率 <= 33.3%
if (pqlh.size() < 1) break;//边界条件,删除的前提是堆中存在最少一个元素
cout << "删除:" << pqlh.getMax();
int oldsize = pqlh.size();
pqlh.delMax();
int newsize = pqlh.size();
if (oldsize > newsize) cout << " 删除成功!" << endl;
else cout << " 删除失败!" << endl;
break;
}
default: { //插入,成功率 <= 66.6%
T key = dice((T)n * 12);
cout << "插入:" << key << " ";
int oldsize = pqlh.size();
pqlh.insert(key);
int newsize = pqlh.size();
if (newsize > oldsize) cout << " 插入成功!" << endl;
else cout << " 插入失败!" << endl;
break;
}
} //switch
} //whil
while (pqlh.size() > 0) {
cout << "删除:" << pqlh.getMax() ;
pqlh.delMax();
if (pqlh.size()) cout << " 删除成功!" << endl;
else cout << "已全部删除!" << endl;
}
}
int main() {
srand((unsigned int)time(NULL));
int i = rand() % 10;
testPQ_LeftHeap<int>(i);
//PQ_LeftHeap<int> pqlh;
//
//pqlh.insert(5);
//pqlh.insert(10);
//pqlh.insert(4);
//cout << pqlh.getMax() << endl;
//pqlh.delMax();
//cout << pqlh.getMax() << endl;
//pqlh.delMax();
//cout << pqlh.getMax() << endl;
system("pause");
return 0;
}
4. 运行结果及截图