基于二叉树的优先队列

  1. 简介

    优先队列:指队列中的元素都被指派一个优先级,元素按优先级最大(最小)出队,存储堆的数组的第一个元素就是最大的(或最小的)。所以用堆作为优先队列的元素载体是合适的。

    队列有两个基本操作:1.入队2.出队。

    队列的特点是先进先出。通常都把队列比喻成排队买东西,大家都很守秩序,先排队的人就先买东西。但是优先队列有所不同,它不遵循先进先出的规则,而是根据队列中元素的优先权,优先权最大的先被取出。通常把优先队列比喻成现实生活中的打印。一个打印店里有很多打印机,每台机器的性能不一样,有的打印机打印很快,有的打印机打印速度很慢。当这些打印机陆陆续续打印完自己的任务时进入排队等候状态。如果我这个时候要打印一份文件,我选的不是第一个排队的打印机,而是性能最好,打印最快的打印机。

    重点:优先级队列,是要看优先级的,谁的优先级更高,谁就先得到权限。不分排队的顺序!

    基本操作:

    empty() 如果队列为空返回真

    pop() 删除对顶元素

    push() 加入一个元素

    size() 返回优先队列中拥有的元素个数

    top() 返回优先队列对顶元素

    在默认的优先队列中,优先级高的先出队。在默认的int型中先出队的为较大的数。

  2. 代码实现(c语言)
#include<stdlib.h>
#include <string.h>
#include <assert.h>
#include "queen.h"
#include "swap.h"
#include "heap.h"
priorityQueen heapAlloc(int size, int n)
{
    priorityQueen q;
    q.length = n;//设置堆的最大长度
    q.heapsize = 0;//目前堆为空、
    q.heap = (void*)malloc(n*size);//分配堆空间
    return q;
}
/***************入队操作*************************
size: 单个元素所占字长
q: 队列
e:入队元素
comp:比较函数(适应最大或最小堆)
************************************************/
void enQueen(priorityQueen*q, int size, void *e, int(*compare)(void*, void*))
{
    if (q->heapsize == q->length)//队列满
        return;
    int i = q->heapsize++;//i为扩大后的堆的最后元素的下标
    memcpy((char*)(q->heap) + i*size, e, size);//heap[i]<--e
    while (i>0 && compare((char*)(q->heap) + parent(i)*size, (char*)(q->heap) + i*size)<0)//parent(i)<heap[i],其大于或小于父节点

    {
        swap((char*)(q->heap) + parent(i)*size, (char*)(q->heap) + i*size, size);
        i = parent(i);//逐个检查父节点
    }
}
void* deQueen(priorityQueen *q, int size, int(*compare)(void*, void*))//出队操作
{
    assert(q->heapsize >= 1);//断言
    void *top = (void*)malloc(size);//暂存最优元素
    memcpy(top, (char*)(q->heap), size);//top<-heap[0]
    q->heapsize--;
    memcpy((char*)q->heap, (char*)q->heap + (q->heapsize)*size, size);//heap[0]<-h[heapsize]

    heapify(q->heap, size, 0, q->heapsize, compare);
    return top;
}
int empty(priorityQueen *q)
{
    return q->heapsize < 1;//检测队列是否为空,若空,返回true
}
void pqeenClear(priorityQueen *q)
{
    free(q->heap);
    q->heap = NULL;
    q->heapsize = q->length = 0;
}
#ifndef _QUEEN_H
#define _QUEEN_H
#ifdef __cplusplus
extern "C" {
#endif

    typedef struct PriorityQueen
    {
        int length;//队列容量
        int heapsize;//队列中当前所有元素的个数
        void *heap;//堆空间
    }priorityQueen;//定义一个优先队列结构体类型
    priorityQueen heapAlloc(int size, int n);
    void enQueen(priorityQueen*q, int size, void *e, int(*compare)(void*, void*));
    void* deQueen(priorityQueen *q, int size, int(*compare)(void*, void*));//出队操作
    int empty(priorityQueen *q);
    void pqeenClear(priorityQueen *q);

#ifdef __cplusplus
{
#endif
#endif /*queen.h*/
#include <stdio.h>
#include <stdlib.h>
#include"compare.h"
#include "sort.h"
#include"merge.h"
#include "partition.h"
#include "heap.h"
#include"queen.h"
int main(int argc, char** argv)
{
    int b[] = { 5, 1, 9, 4, 6, 2, 0, 3, 8, 7 }, i;
    priorityQueen q = heapAlloc(sizeof(int), 10);
    for (i = 0; i < 10; i++)
    {
        enQueen(&q, sizeof(int), b + i, intLess);
    }
    while (!empty(&q))
        printf("%d   ", *(int*)deQueen(&q, sizeof(int), intLess));
    printf("\n");
    pqeenClear(&q);

    system("pause");
    return EXIT_SUCCESS;
}
  1. 代码实现(c++)

    这里通过定义一个模版类PriQueue来实现优先队列操作

#ifndef _QUEUE_H
#define _QUEUE_H
#include <assert.h>
#include <vector>
using namespace std;
template<typename T,typename Comparator>
class PriQueue
{
private:
    vector<T> heap;//队列中元素载体
    int heapSize;//队列中元素的个数
public:

    PriQueue():heapSize(0){ }//使用构造函数初始化列表进行初始化
    void enQueue(T e)
    {
        heapSize++;
        heap.push_back(e);
        push_heap(heap.begin(), heap.end(), Comparator());//入队
    }
    T deQueue()//出队
    {
        assert(heapSize >= 1);
        pop_heap(heap.begin(), heap.end(), Comparator());//将 heap[0]和 heap[heapSize-1] 交换,并将 heap[0...heapSize-2]按比较规则构成一个堆
        heapSize--;
        T top = heap[heapSize];//保存heap中的最后一个元素到top
        heap.erase(heap.end() - 1);//删除heap中的最后一个元素
        return top;
    }
    bool empty()
    {
        return heapSize < 1;
    }
};
#endif  /*_QUEUE_H*/

测试代码:


#include "stdafx.h"
#include<string.h>
#include <stdlib.h>
#include <vector>
#include <iterator>
#include <iostream>
#include<algorithm>
#include <functional>//定义运算函数(代替运算符)
#include "sort.h"
#include "merge.h"
#include "partition.h"
#include "heap.h"
#include "queue.h"
using namespace std;
int main(int argc, _TCHAR* argv[])
{
    int a[]={4,1,3,2,16,9,10,14,8,7},i;
    vector<int> va = vector<int>(a, a + 10);//用数组创建vector对象
    PriQueue<int, less<int>> q;  //声明一个优先队列对象
    for (i = 0; i < 10; i++)
        q.enQueue(a[i]);//入队
    while (!q.empty())
        cout << q.deQueue() << " ";
    cout << endl;

    system("pause");

    return 0;
}

运行结果:16 14 10 9 8 7 4 3 2 1

STL 模版库类priority_queue

#include<iostream>
#include <queue>
using namespace std;
int main(int argc, _TCHAR* argv[])
{
    int a[]={4,1,3,2,16,9,10,14,8,7},i;
    vector<int> va = vector<int>(a, a + 10);//用数组创建vector对象
priority_queue<int, vector<int>, less<int>> p;
    for (i = 0; i < 10; i++)
        p.push(a[i]);
    while (!p.empty())
    {
        cout << p.top() << " ";
        p.pop();

    }
    cout << endl;
    system("pause");

    return 0;
}
时间: 2024-08-28 01:07:07

基于二叉树的优先队列的相关文章

数据结构之基于堆的优先队列

优先队列的最重要的操作:删除最大元素(或最小)和插入元素.数据结构二叉堆能够很好的实现队列的基本操作.二叉堆的结点按照层级顺序放入数组,用长度为N+1的私有数组pq来表示一个大小为N的堆(堆元素放在pq[1]至pq[N]之间,为方便计数,未使用pq[0]),跟节点在位置1,它的子结点在位置2和3,以此类推.位置k的节点的父节点位置为k/2,它的两个子节点位置分别为2k和2k+1.当一颗二叉树的每个节点都大于等于它的两个子节点时,称为大根堆.当一颗二叉树的每个节点都小于等于它的两个子节点时,称为小

基于二叉树和数组实现限制长度的最优Huffman编码

具体介绍详见上篇博客:基于二叉树和双向链表实现限制长度的最优Huffman编码 基于数组和基于链表的实现方式在效率上有明显区别: 编码256个符号,符号权重为1...256,限制长度为16,循环编码1w次,Release模式下.基于链表的耗时为8972ms,基于数组的耗时为1793ms,速度是链表实现方式的5倍. 详细代码例如以下: //Reference:A fast algorithm for optimal length-limited Huffman codes.pdf,http://p

第一篇博客——基于数组的优先队列(java版)

看过园子里和CSND上那么多大牛精彩的博客后,早就按捺不住想亲手写上几篇.奈何每次坐在电脑前准备敲字的时候,立马赶到浑身不自在,无从下手.实在是因为自高考之后,大学以来,本人几乎就再没动笔写过一篇文字,写作水平退化实在严重.今天鼓起勇气开始写作博客,一方面希望通过多写慢慢地找回写作的感觉,一方面也希望通过博客和大家多多交流,共同进步. 既然是第一次试手,就写个简单易懂的内容——优先队列. 话不多说,先上代码. 1 /** 2 * @author Mr Left 3 * @version 1.0

基于二叉树和双向链表实现限制长度的最优Huffman编码

该代码采用二叉树结合双向链表实现了限制长度的最优Huffman编码,本文代码中的权重全部采用整数值表示.http://pan.baidu.com/s/1mgHn8lq 算法原理详见:A fast algorithm for optimal length-limited Huffman codes.pdf 示例:符号ABCDE的权重分别为10,6,2,1,1 不限制长度的最优Huffman编码为A:0,B:10,C:110,D:1110,E:1111,平均码长为1.8bits/symbol; 限制

基于堆的优先队列

源代码如下 #include <stdio.h> #include <stdlib.h> typedef struct Item *node; struct Item{ int data; char c; }; static Item *pq; static int N ; void swap(Item &a,Item &b){struct Item t = a;a = b;b = t;} //自底向上堆化 完全二叉树 父节点的关键值大于等于子节点关键值 void

基于二叉树的抢劫问题 leetcode337

1 /** 2 * Definition for a binary tree node. 3 * struct TreeNode { 4 * int val; 5 * TreeNode *left; 6 * TreeNode *right; 7 * TreeNode(int x) : val(x), left(NULL), right(NULL) {} 8 * }; 9 */ 10 11 class Solution { 12 public: 13 int rob(TreeNode* root)

算法(第4版)-2.4 优先队列

定义:一种支持删除最大元素和插入元素的数据结构. 经典实现:基于二叉堆数据结构. 2.4.1 API 1. 只要我们能够高效地实现insert()和delMin(),下面的优先队列用例中调用了MinPQ的TopM就能使用优先队列解决这个问题. 2.4.2 初级实现 1. 数组实现(无序):修改pop(),先交换再删除,相当于选择排序(个人认为). -> 惰性方法 2. 数组实现(有序):修改insert(),每次插入后保证最大值在栈的顶部. -> 积极方法 3. 链表表示法:用基于链表的下压栈

数据结构----------------优先队列

优先队列 主要用于:1.插入 2.删除最大元素 基于实现这两项功能,用二叉堆来实现, 分析: ____________MaxPQ<Key>implementsIterator<Key>_______________________ insert() delMax()    优先队列的2个主要功能 ----------------------------------------------------------------------------------------------

0038数据结构之堆和优先队列

优先队列:出队顺序和入队顺序无关,而是和优先级有关(优先级高的先出队) 如果使用普通线性结构或者顺序线性结构实现优先队列,出队或者入队总有一方是O(n)级别的:如果使用堆实现优先队列,能使入队和出队的时间复杂度都是O(logn),效率是极高的. 二叉堆是一颗完全二叉树,不一定是满二叉树,但是确实节点的那部分一定是在整棵树的右下侧.满足的规律:1)根节点最大, 2)确实节点的那部分在整棵树的右下侧.(低层次的节点不一定大于高层次的节点) 下图是一颗最大堆: 可以用数组存储: 从数组1位置开始存储: