二项队列 C++实现

#ifndef BINOMIAL_QUEUE_H
#define BINOMIAL_QUEUE_H

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

template <typename Comparable>
class BinomialQueue
{
public:
    BinomialQueue() : theTrees(DEFAULT_TREES)
    {
        for (auto & root : theTrees)
            root = nullptr;
        currentSize = 0;
    }

    BinomialQueue(const Comparable & item) : theTrees(1), currentSize{1}
    {
        theTrees[0] = new BinomialNode{item, nullptr, nullptr};
    }

    BinomialQueue(const BinomialQueue & rhs)
     : theTrees(rhs.theTrees.size()), currentSize{rhs.currentSize}
    {
        for (int i = 0; i < rhs.theTrees.size(); ++i)
            theTrees[i] = clone(rhs.theTrees[i]);
    }

    BinomialQueue(BinomialQueue && rhs)
     : theTrees{std::move(rhs.theTrees)}, currentSize{rhs.currentSize} {}

    ~BinomialQueue()
    {
        makeEmpty();
    }

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

    BinomialQueue & operator=(BinomialQueue && rhs)
    {
        std::swap(currentSize, rhs.currentSize);
        std::swap(theTrees, rhs.theTrees);
        return *this;
    }

    bool isEmpty() const
    {
        return currentSize == 0;
    }

    const Comparable & findMin() const
    {
        if (isEmpty())
            throw UnderflowException{};
        return theTrees[findMinIndex()]->element;
    }

    void insert(const Comparable & x)
    {
        BinomialQueue oneItem{x};
        merge(oneItem);
    }

    void insert(Comparable && x)
    {
        BinomialQueue oneItem{std::move(x)};
        merge(oneItem);
    }

    void deleteMin()
    {
        Comparable x;
        deleteMin(x);
    }

    void deleteMin(Comparable & minItem)
    {
        if (isEmpty())
            throw UnderflowException{};
        int minIndex = findMinIndex();
        minIndex = theTrees[minIndex]->element;
        BinomialNode *oldRoot = theTrees[minIndex];
        BinomialNode *deletedTree = oldRoot->leftchild;
        delete oldRoot;

        BinomialQueue deletedQueue;
        deletedQueue.theTrees.resize(minIndex + 1);
        deletedQueue.currentSize = (1 << minIndex) - 1;
        for (int j = minIndex - 1; j >= 0; --j) {
            deletedQueue.theTrees[j] = deletedTree;
            deletedTree = deletedTree->nextSibling;
            deletedQueue.theTrees[j]->nextSibling = nullptr;
        }

        theTrees[minIndex] = nullptr;
        currentSize -= deletedQueue.currentSize + 1;

        merge(deletedQueue);
    }

    void makeEmpty()
    {
        currentSize = 0;
        for (auto & root : theTrees)
            makeEmpty(root);
    }

    void merge(BinomialQueue & rhs)
    {
        if (this == &rhs)
            return;

        currentSize += rhs.currentSize;

        if (currentSize > capacity()) {
            int oldNumTrees = theTrees.size();
            int newNumTrees = max(theTrees.size(), rhs.theTrees.size()) + 1;
            theTrees.resize(newNumTrees);
            for (int i = oldNumTrees; i < newNumTrees; ++i)
                theTrees[i] = nullptr;
        }

        BinomialNode *carry = nullptr;
        for (int i = 0, j = 1; j <= currentSize; ++i, j *= 2) {
            BinomialNode *t1 = theTrees[i];
            BinomialNode *t2 = i < rhs.theTrees.size() ? rhs.theTrees[i] : nullptr;
            int whichCase = t1 == nullptr ? 0 : 1;
            whichCase += t2 == nullptr ? 0 : 2;
            whichCase += carry == nullptr ? 0 : 4;

            switch (whichCase) {
                case 0: /* No trees */
                case 1: /* Only this */
                    break;
                case 2:
                    theTrees[i] = t2; /* Only rhs */
                    rhs.theTrees[i] = nullptr;
                    break;
                case 4: /* Only carry */
                    theTrees[i] = carry;
                    carry = nullptr;
                    break;
                case 3: /* this and rhs */
                    carry = combineTrees(t1, t2);
                    theTrees[i] = rhs.theTrees[i] = nullptr;
                    break;
                case 5: /* this and carry */
                    carry = combineTrees(t1, carry);
                    theTrees[i] = nullptr;
                    break;
                case 6: /* rhs and carry */
                    carry = combineTrees(t2, carry);
                    rhs.theTrees[i] = nullptr;
                    break;
                case 7: /* All three */
                    theTrees[i] = carry;
                    carry = combineTrees(t1, t2);
                    rhs.theTrees[i] = nullptr;
                    break;
            }
        }
        for (auto & root : rhs.theTrees)
            root = nullptr;
        rhs.currentSize = 0;
    }

private:
    struct BinomialNode
    {
        Comparable element;
        BinomialNode *leftchild;
        BinomialNode *nextSibling;

        BinomialNode(const Comparable & e, BinomialNode *lt, BinomialNode *rt)
         : element{e}, leftchild{lt}, nextSibling{rt} {}

        BinomialNode(Comparable && e, BinomialNode *lt, BinomialNode *rt)
         : element{std::move(e)}, leftchild{lt}, nextSibling{rt} {}
    };

    const static int DEFAULT_TREES = 1;

    vector<BinomialNode *> theTrees;
    int currentSize;

    int findMinIndex() const
    {
        int i;
        int minIndex;
        for (i = 0; theTrees[i] == nullptr; ++i)
            ;
        for (minIndex = i; i < theTrees.size(); ++i)
            if (theTrees[i] != nullptr && theTrees[i]->element < theTrees[minIndex]->element)
                minIndex = i;

        return minIndex;
    }

    int capacity() const
    {
        return (1 << theTrees.size()) - 1;
    }

    BinomialNode * combineTrees(BinomialNode *t1, BinomialNode *t2)
    {
        if (t2->element < t1->element)
            return combineTrees(t2, t1);
        t2->nextSibling = t1->leftchild;
        t1->leftchild = t2;
        return t1;
    }

    void makeEmpty(BinomialNode * & t)
    {
        if (t != nullptr) {
            makeEmpty(t->leftchild);
            makeEmpty(t->nextSibling);
            delete t;
            t = nullptr;
        }
    }

    BinomialNode * clone(BinomialNode * t) const
    {
        if (t == nullptr)
            return nullptr;
        else
            return new BinomialNode{t->element, clone(t->leftchild), clone(t->nextSibling)};
    }
};

#endif
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
matrix.h: Simple matrix class dsexceptions.h: Simple exception classes Fig01_02.cpp: A simple recursive routine with a test program Fig01_03.cpp: An example of infinite recursion Fig01_04.cpp: Recursive routine to print numbers, with a test program Fig01_05.cpp: Simplest IntCell class, with a test program Fig01_06.cpp: IntCell class with a few extras, with a test program IntCell.h: IntCell class interface (Fig 1.7) IntCell.cpp: IntCell class implementation (Fig 1.8) TestIntCell.cpp: IntCell test program (Fig 1.9) (need to compile IntCell.cpp also) Fig01_10.cpp: Illustration of using the vector class Fig01_11.cpp: Dynamically allocating an IntCell object (lame) BuggyIntCell.cpp: Buggy IntCell class implementation (Figs 1.16 and 1.17) Fig01_18.cpp: IntCell class with pointers and Big Five FindMax.cpp: Function template FindMax (Figs 1.19 and 1.20) Fig01_21.cpp: MemoryCell class template without separation Fig01_25.cpp: Using function objects: Case insensitive string comparison LambdaExample.cpp: (Not in the book): rewriting Fig 1.25 with lambdas MaxSumTest.cpp: Various maximum subsequence sum algorithms Fig02_09.cpp: Test program for binary search Fig02_10.cpp: Euclid's algorithm, with a test program Fig02_11.cpp: Recursive exponentiation algorithm, with a test program RemoveEveryOtherItem.cpp: Remove every other item in a collection Vector.h: Vector class List.h: List class BinarySearchTree.h: Binary search tree TestBinarySearchTree.cpp: Test program for binary search tree AvlTree.h: AVL tree TestAvlTree.cpp: Test program for AVL trees mapDemo.cpp: Map demos WordLadder.cpp: Word Ladder Program and Word Changing Utilities SeparateChaining.h: Header file for separate chaining SeparateChaining.cpp: Implementation for separate chaining TestSeparateChaining.cpp: Test program for separate chaining hash tables (need to compile SeparateChaining.cpp also) QuadraticProbing.h: Header file for quadratic probing hash table QuadraticProbing.cpp: Implementation for quadratic probing hash table TestQuadraticProbing.cpp: Test program for quadratic probing hash tables (need to compile QuadraticProbing.cpp also) CuckooHashTable.h: Header file for cuckoo hash table CuckooHashTable.cpp: Implementation for cuckoo hash table TestCuckooHashTable.cpp: Test program for cuckoo hash tables (need to compile CuckooHashTable.cpp also) CaseInsensitiveHashTable.cpp: Case insensitive hash table from STL (Figure 5.23) BinaryHeap.h: Binary heap TestBinaryHeap.cpp: Test program for binary heaps LeftistHeap.h: Leftist heap TestLeftistHeap.cpp: Test program for leftist heaps BinomialQueue.h: Binomial queue TestBinomialQueue.cpp: Test program for binomial queues TestPQ.cpp: Priority Queue Demo Sort.h: A collection of sorting and selection routines TestSort.cpp: Test program for sorting and selection routines RadixSort.cpp: Radix sorts DisjSets.h: Header file for disjoint sets algorithms DisjSets.cpp: Efficient implementation of disjoint sets algorithm TestFastDisjSets.cpp: Test program for disjoint sets algorithm WordLadder.cpp: Word Ladder Program and Word Changing Utilities Fig10_38.cpp: Simple matrix multiplication algorithm with a test program Fig10_40.cpp: Algorithms to compute Fibonacci numbers Fig10_43.cpp: Inefficient recursive algorithm (see text) Fig10_45.cpp: Better algorithm to replace fig10_43.c (see text) Fig10_46.cpp: Dynamic programming algorithm for optimal chain matrix multiplication, with a test program Fig10_53.cpp: All-pairs algorithm, with a test program Random.h: Header file for random number class Random.cpp: Implementation for random number class TestRandom.cpp: Test program for random number class UniformRandom.h: Random number class using standard library Fig10_63.cpp: Randomized primality testing algorithm, with a test program SplayTree.h: Top-down splay tree TestSplayTree.cpp: Test program for splay trees RedBlackTree.h: Top-down red black tree TestRedBlackTree.cpp: Test program for red black trees Treap.h: Treap TestTreap.cpp: Test program for treap SuffixArray.cpp: Suffix array KdTree.cpp: Implementation and test program for k-d trees PairingHeap.h: Pairing heap TestPairingHeap.cpp: Test program for pairing heaps MemoryCell.h: MemoryCell class interface (Appendix) MemoryCell.cpp: MemoryCell class implementation (Appendix) MemoryCellExpand.cpp: MemoryCell instantiation file (Appendix) TestMemoryCell.cpp: MemoryCell test program (Appendix)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值