堆与优先队列

Posted 声声醉如兰

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了堆与优先队列相关的知识,希望对你有一定的参考价值。

当我们需要高效的完成以下操作时:

  1.插入一个元素

  2.取得最小(最大)的数值,并且删除

能够完成这种操作的数据结构叫做优先队列

而能够使用二叉树,完成这种操作的数据结构叫做堆(二叉堆)

 

堆与优先队列的时间复杂度:

若共有n个元素,则可在O(logn)的时间内完成上述两种操作

 

堆的结构如下图:

堆最重要的性质就是儿子的值一定不小于父亲的值,且堆从上到下,从左到右紧密排列。

堆的操作:

当我们希望向堆中插入元素时,堆的内部会进行如下操作(以插入元素3为例):

(1.在堆的末尾插入该值)

(2.不断向上提升该元素,直到满足堆的性质为止)

 

当我们需要删除堆中的最小值时,堆的内部则进行如下操作

(1.将堆的最后一个节点复制到根节点位置,而后删除最后一个节点)

(2.不断向下交换,直到满足堆的性质为止)

 

 

堆的代码实现:

int heap[MAXSIZE],hsize=0;

void Push(int x) //向堆中添加元素
{
    int i = hsize++; //堆的大小增加
    while(i > 0)
    {
        int father_id = (i - 1)/2; //父亲节点的编号
        
        if(heap[i] > heap[father_id]) //判断是否满足堆的性质
            break;
        
        heap[i] = heap[father_id]; //将父亲节点下放,将新增元素上移
        i = father_id;
    }
    heap[i] = x;
}

void Pop() //弹出堆中的最小值
{
    int root = heap[0]; //记录最小值
    
    int x = heap[hsize--]; //堆的大小减少
    
    int i = 0;
    
    while(i * 2 + 1 < hsize)
    {
        int lson = i * 2 + 1; //左儿子节点
        int rsong = lson + 1; //右儿子节点
        
        if(lson > x && rson > x) //判断是否满足堆的性质
            break;
            
        if(heap[lson] < heap[rson]) //选择与儿子交换
        {
            heap[i] = heap[lson];
            i = lson;
        }
        else if(ron < hsize)
        {
            heap[i] = heap[rson];
            i = rson;
        }
    }
    
    heap[i] = x;
    
    return root;
}
View Code

 STL中的set:

在C++中,我们可以通过 <set>来实现堆的相关操作,使用set,我们可以方便并且迅速的完成数据检索

常用的set操作:

  1.声明:set<int> s;//声明一个存储int类型数据的堆s

  2.插入元素:s.insert(1);//插入元素1

  3.删除元素:s.erase(1);//删除键值为1的元素

  4.查询元素是否存在:

    1.    ste<int>::iterator it;
         it = s.find(1);
         if(it == s.end())
              printf("No Find\\n");
         else
              printf("Find\\n");

    2.    if(s.find(1) != 0)
              printf("Find");
         else
              printf("No Find\\n");

  5.遍历: ste<int>::iterator it; //按键值从小到大输出

       for(it=s.begin();it!=s.end();it++)
              printf("%d\\n",*it);

STL中的优先队列:

在C++中,STL里的priority_queue可以完成优先队列的实现,代码如下

 

#include<queue>
#include<cstdio>
using namespace std;

int date[5];

int main()
{
    priority_queue<int> Q; //默认为最大值优先
    priority_queue<int,vector<int>,greater<int> > Q1; //最小值优先
    priority_queue<int,vector<int>,less<int> > Q2; //最大值优先

    for(int i=1;i<=3;i++)
    {
        scanf("%d",&date[i]);
        Q.push(date[i]); //插入元素
    }


    while(!Q.empty())
    {
        int x = Q.top(); //读取队头元素
        Q.pop(); //弹出元素
        printf("%d\\n",x);
    }

    return 0;
}
View Code

 

以上是关于堆与优先队列的主要内容,如果未能解决你的问题,请参考以下文章

数据结构_二叉树Ⅲ——堆与优先队列

二叉堆与优先队列

堆与栈

# Java 常用代码片段

# Java 常用代码片段

堆 与 堆排序