【数据结构】回顾优先队列(堆)

简介:

1.优先队列有两项基本操作:插入(insert)和删除最小项(deleteMin),后者的工作是找出、返回和删除优先队列中最小的元素。而insert操作则等价于enqueue(入队),deleteMin则等价于dequeue(出队)。补充:C++提供2个版本的deleteMin,一个删除最小项,另一个在删除最小项的同时在通过引用传递的对象中存储所删除的值。

这里写图片描述

2.优先队列的类接口

template <typename Comparable>
class BinaryHeap
{
public:
    explicit BinaryHeap(int capacity=100);
    explicit BinaryHeap(const vector<Comparable> & items);

    bool isEmpty() const;
    const Comparable & findMin() const;

    void insert(const Comparable & x);
    void deleleMin();
    void deleteMin(Comparable & minItem);
    void makeEmpty();

private:
    int currentSize;
    vector<Comparable> array;
    void buildHeap();
    void percolateDown(int hole);
};

3.插入到一个二叉堆

void insert(const Comparable & x)
{
    if(currentSize==array.size()-1)
        array.resize(array.size()*2);

    int hole=++currentSize;
    for(;hole>1&&x<array[hole/2];hole/=2)
        array[hole] =array[hole/2];
    array[hole]=x;
}

4.在二叉堆中执行deleteMin

void deleteMin()
{
    if(isEmpty())
        throw UnderflowException();

    array[1]=array[currentSize--];
    percolateDown(1);
}

void deleteMin(Comparable & minItem)
{
    if(isEmpty())
        throw UnderflowException();

    minItem=array[1];
    arrary[1]=array[currentSize--];
    percolateDown(1);
}

void percolateDown(int hole)
{
    int child;
    Comparable tmp=array[hole];

    for(;hole*2<=currentSize;hole=child)
    {
        child=hole*2;
        if(child!=currentSize&&array[child+1]<array[child])
            child++;
        if(array[child]<tmp)
            array[hole]=array[child];
        else 
            break;
    }
    array[hole]=tmp;
}

5.左式堆(leftist heap)像二叉堆那样既有结构性质,又有堆序性质。左序堆也是二叉树,它和二叉树的唯一区别是:左式堆不是理想平衡的(perfectly balanced),而且事实上是趋于非常不平衡的。左式堆的性质:对于堆中的每一个结点X,左儿子的零路径至少于右儿子的零路径长一样大。由于左式堆是趋向于加深左路径,因此右路径应该很短,沿左式堆右侧的右路径确实是该堆中最短的路径。否则就会存在一条路径通过某个结点X并取得左儿子,此时X就破坏了左式堆的性质。

6.对左式堆的基本操作是合并(插入只是合并的特殊情形)。左式堆类型声明:

template <typename Comparable>
class LeftistHeap
{
public:
    LeftistHeap();
    LeftistHeap(const LeftistHeap & rhs);
    ~LeftistHeap();

    bool isEmpty() const;
    const Comparable & findMin() const;

    void insert(const Comparable & x);
    void deleteMin();
    void deleteMin(Comparable & minItem);
    void makeEmpty();
    void merge(LeftistHeap & rhs);

    const LeftistHeap & operator=(const LeftistHeap & rhs);

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

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

    LeftistNode *root;

    LeftistNode *merge (LeftistNode *h1,LeftistNode *h2);
    LeftistNode *merge1(LeftistNode *h1,LeftistNode *h2);

    void swapChildren(LeftistNode *t);
    void reclainMemory(LeftistNode *t);
    LeftistNode *clone(LeftistNode *t) const;
};

7.合并左式堆的驱动程序和实际程序

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

    root=merge(root,rhs.root);
    rhs.root=NULL;
}

LeftistNode * merge(LeftistNode *h1,LeftistNode *h2)
{
    if(h1==NULL)
        return h2;
    if(h2==NULL)
        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==NULL)
        h1->left=h2;
    else
    {
        h1->right=merge(h1->right,h2);
        if(h1->left->npl<h1->right-np1)
            swapChildren(h1);
        h1->npl=h1->right->npl+1;
    }
    return h1;
}

8.左式堆的insert程序和deleteMin程序

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

void deleteMin()
{
    if(isEmpty())
        throw UnderflowException();

    LeftistNode *oldRoot=root;
    root=merge(root->left,root->right);
    delete oldRoot;
}

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

9.二项队列不是一棵堆序的树,而是堆序的集合,称为森林(forest)。

这里写图片描述

这里写图片描述

10.二项队列类构架及结点定义:


template <typename Comparable>
class BinomialQueue
{
public:
    BinomialQueue();
    BinomialQueue(const Comparable & item);
    BinomialQueue(const BinomialQueue & rhs);
    ~BinomialQueue();

    bool isEmpty() const;
    const Comparable &  findMin() const;

    void insert(const Comparable & x);
    void deleteMin();
    void deleteMin(Comparable & minItem);

    void makeEmpty();
    void merge(BinomialQueue & rhs);

    const BinomialQueue & operator = (const BinomialQueue & rhs);

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

        BinomialNode(const Comparable & theElement,
                     BinomialNode *lt,BinomialNode *rt)
            :element(theElement).leftchild(lt).nextSiblig(rt){}
    };

    enum {DEFAULT_TREES=1};

    int currentSize;
    vector<BinomialNode*> theTrees;

    int findMinIndex() const;
    int capacity() const;
    BinomialNode * combineTrees(BinomialNode *t1,BinomialNode *t2);
    void makeEmpty(BinomialNode * & t);
    BinomialNode * clone(BinomialNode * t) const;
};

11.在STL中,二叉堆是通过称为priority_queue的类模板实现的,该类模板可以在标准头文件queue中找到。STL 实现了一个最大堆而不是最小堆,因此所访问的项就是最大的项而不是最小的项。其键成员函数如下:

void push(const Object & x);
const Object & top() const;
void pop();
bool empty();
void clear();



感谢您的访问,希望对您有所帮助。

欢迎大家关注或收藏、评论或点赞。


为使本文得到斧正和提问,转载请注明出处:
http://blog.csdn.net/nomasp


目录
相关文章
|
4天前
|
存储 算法 Java
散列表的数据结构以及对象在JVM堆中的存储过程
本文介绍了散列表的基本概念及其在JVM中的应用,详细讲解了散列表的结构、对象存储过程、Hashtable的扩容机制及与HashMap的区别。通过实例和图解,帮助读者理解散列表的工作原理和优化策略。
16 1
散列表的数据结构以及对象在JVM堆中的存储过程
|
6天前
|
存储 搜索推荐 算法
【数据结构】树型结构详解 + 堆的实现(c语言)(附源码)
本文介绍了树和二叉树的基本概念及结构,重点讲解了堆这一重要的数据结构。堆是一种特殊的完全二叉树,常用于实现优先队列和高效的排序算法(如堆排序)。文章详细描述了堆的性质、存储方式及其实现方法,包括插入、删除和取堆顶数据等操作的具体实现。通过这些内容,读者可以全面了解堆的原理和应用。
46 16
|
28天前
|
存储 JavaScript 前端开发
为什么基础数据类型存放在栈中,而引用数据类型存放在堆中?
为什么基础数据类型存放在栈中,而引用数据类型存放在堆中?
63 1
|
2月前
|
存储 Java
【数据结构】优先级队列(堆)从实现到应用详解
本文介绍了优先级队列的概念及其底层数据结构——堆。优先级队列根据元素的优先级而非插入顺序进行出队操作。JDK1.8中的`PriorityQueue`使用堆实现,堆分为大根堆和小根堆。大根堆中每个节点的值都不小于其子节点的值,小根堆则相反。文章详细讲解了如何通过数组模拟实现堆,并提供了创建、插入、删除以及获取堆顶元素的具体步骤。此外,还介绍了堆排序及解决Top K问题的应用,并展示了Java中`PriorityQueue`的基本用法和注意事项。
50 5
【数据结构】优先级队列(堆)从实现到应用详解
|
1月前
|
存储 算法 调度
数据结构--二叉树的顺序实现(堆实现)
数据结构--二叉树的顺序实现(堆实现)
|
1月前
|
存储 算法 分布式数据库
【初阶数据结构】理解堆的特性与应用:深入探索完全二叉树的独特魅力
【初阶数据结构】理解堆的特性与应用:深入探索完全二叉树的独特魅力
|
29天前
|
存储 算法
探索数据结构:分支的世界之二叉树与堆
探索数据结构:分支的世界之二叉树与堆
|
1月前
|
存储 算法 Java
【用Java学习数据结构系列】用堆实现优先级队列
【用Java学习数据结构系列】用堆实现优先级队列
29 0
|
1月前
|
存储 算法
【数据结构】二叉树——顺序结构——堆及其实现
【数据结构】二叉树——顺序结构——堆及其实现
|
1月前
【数据结构】大根堆和小根堆
【数据结构】大根堆和小根堆
21 0