左式堆C++实现

左式堆中每一个节点left child的零路径长至少与right child的零路径长一样。任一节点的零路径长为从该节点到一个不具有两个儿子的节点的最短路径的长。下图为一棵左式树。
在这里插入图片描述
对左式堆的基本操作是合并,为了合并两个堆,递归的做法是先比较它们的根,递归地将具有较大根值的堆与具有较小根值的堆的右子堆合并。

#ifndef LEFTIST_HEAP_H
#define LEFTIST_HEAP_H

#include "dsexceptions.h"
#include <iostream>
using namespace std;

template <typename Comparable>
class LeftistHeap
{
public:
    LeftistHeap() : root{ nullptr } {}

    LeftistHeap(const LeftistHeap & rhs) : root{ nullptr }
    {
        root = clone(rhs.root);
    }

    LeftistHeap(LeftistHeap && rhs) : root{ rhs.root }
    {
        rhs.root = nullptr;
    }

    ~LeftistHeap()
    {
        makeEmpty();
    }

    LeftistHeap & operator=(const LeftistHeap & rhs)
    {
        LeftistHeap copy = rhs;
        std::swap(*this, copy);
        return *this;
    }

    LeftistHeap & operator=(LeftistHeap && rhs)
    {
        std::swap(root, rhs.root);
        return *this; 
    }

    bool isEmpty() const
    {
        return root == nullptr;
    }

    const Comparable & findMin() const
    {
        if (isEmpty())
            throw UnderflowException{};
        return root->element;
    }

    void insert(const Comparable & x)
    {
        root = merge(new LeftistNode{x}, root);
    }

    void insert(Comparable && x)
    {
        root = merge(new LeftistNode{std::move(x)}, root);
    }

    void deleteMin()
    {
        if (isEmpty())
            throw UnderflowException{};
        LeftistNode *oldRoot = root;
        root = merge(root->left, root->right);
        delete oldRoot;
    }

    void deleteMin(Comparable & minItem)
    {
        minItem = findMin();
        deleteMin();
    }

    void makeEmpty()
    {
        reclaimMemory(root);
        root = nullptr;
    }

    void merge(LeftistHeap & rhs)
    {
        if (this == &rhs)
            return;
        root = merge(root, rhs.root);
        rhs.root = nullptr;
    }

private:
    struct LeftistNode
    {
        Comparable element;
        LeftistNode *left;
        LeftistNode *right;
        int npl;

        LeftistNode(const Comparable & e, LeftistNode *lt = nullptr,
                    LeftistNode *rt = nullptr, int np = 0)
         : element{e}, left{lt}, right{rt}, npl{np} {}

        LeftistNode(Comparable && e, LeftistNode *lt = nullptr,
                    LeftistNode *rt = nullptr, int np = 0)
         : element{std::move(e)}, left{lt}, right{rt}, npl{np} {}
    };

    LeftistNode *root;

    LeftistNode *merge(LeftistNode *h1, LeftistNode *h2)
    {
        if (h1 == nullptr)
            return h2;
        if (h2 == nullptr)
            return h1;
        if (h1->element < h2->element)
            return merge1(h1, h2);
        else
            return merge1(h2, h1);
    }

    LeftistNode *merge1(LeftistNode *h1, LeftistNode *h2)
    {
        if (h1->left == nullptr)
            h1->left = h2;
        else {
            h1->right = merge(h1->right, h2);
            if (h1->left->npl < h1->right->npl)
                swapChildren(h1);
            h1->npl = h1->right->npl + 1;
        }
        return h1;
    }

    void swapChildren(LeftistNode *t)
    {
        LeftistNode *tmp = t->left;
        t->left = t->right;
        t->right = tmp;
    }

    void reclaimMemory(LeftistNode *t)
    {
        if (t != nullptr) {
            reclaimMemory(t->left);
            reclaimMemory(t->right);
            delete t;
        }
    }

    LeftistNode *clone(LeftistNode *t) const
    {
        if (t == nullptr)
            return nullptr;
        else
            return new LeftistNode{t->element, clone(t->left), clone(t->right), t->npl};
    }
};

#endif
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值