C++ 数据结构学习 ---- 左式堆

目录

1 头文件

1.1 二叉树头文件

1.2 左式堆头文件

1.3 Dice头文件

2. 相关函数

2.1 插入函数

2.2 删除函数

2.3 获取函数

2.4 合并函数

3. 完整代码

4. 运行结果及截图


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. 运行结果及截图

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值