`
luozhong915127
  • 浏览: 185989 次
  • 性别: Icon_minigender_1
  • 来自: 湖南
文章分类
社区版块
存档分类
最新评论

优先队列与堆的解析

阅读更多

    队列的特点是先进先出。通常都把队列比喻成排队买东西,大家都很守秩序,先排队的人就先买东西。
    但是优先队列有所不同,它不遵循先进先出的规则,而是根据队列中元素的优先权,优先权最大的先被取出。通常把优先队列比喻成现实生活中的打印。一个打印店里有很多打印机,每台机器的性能不一样,有的打印机打印很快,有的打印机打印速度很慢。当这些打印机陆陆续续打印完自己的任务时进入排队等候状态。如果我这个时候要打印一份文件,我选的不是第一个排队的打印机,而是性能最好,打印最快的打印机。
    优先队列的特点就是将存储的元素根据其优先权的高低,先取出优先权高的元素。所以,优先队列的实现方法有很多。
如果优先权的范围是已知的,那么就可以尝试用一个二维数组来实现优先队列。每一行表示一个优先级别。例如用大小为a[10][10]的二维数组来实现一个优先队列,a[0]表示一个优先级别,里面存放优先级为0的元素,a[10]则存放优先级最高的元素。这样根据元素的优先级进行存储,取出元素的时候,根据优先级,先取出优先级最高的元素。
    上面的方法在优先权范围已知且比较集中可以估计的情况下可以适用,但是如果优先权的范围不清楚,或者间隔很大,就不再使用。实现优先队列也可以用一个链表队列加以实现。链表的节点数据包含两个部分,队列的数据项和该数据项的优先权。将元素存入链表,需要用时,遍历链表,查找优先权最大的数据项。
    还可以用下面的方法。用一个数组来存放优先权,另外一个相应的数组存放要存放的元素。由于,不同的元素可能会有相同的优先权。所以,存放元素的数组中不是直接存放元素,而是存放链表,就像用挂链法来解决哈希冲突一样。当有相同优先权的元素不止一个时,则挂在相应数组索引位置的链表上,如图1。根据优先权数组中存放的优先权,来取得优先权最大的元素。由于数组查找比链表要快,所以,这个方法比上面的方法的改进。



 

Java代码 

private int[] priority   
private ElementNode[] elements   
private int highest   
private int manyItems   
private int PriotityCount  
private int[] priority

private ElementNode[] elements

private int highest

private int manyItems

private int PriotityCount

priority数组是用来存放优先权的,初始的值都是0,之后赋予的优先权值必须都大于0。

Elements是用来存放元素链表的数组。初始值都是null,然后往里面挂上链表。

highest元素是记录优先权最大的元素的数组索引位置,这样,可以方便使用,提高效  率。因为每次要查找优先权最大的元素时,不需要再重新查找。

manyItems用来记录队列中已经存放的元素个数。

PriotityCount用来记录不同优先权的数目。因为有链表的存在,manyItems不能衡量  数组是否满了,而PriotityCount对应的是优先权数组中的使用优先权个数,可以衡量数  组使用情况。

两个私有方法: 

Java代码   

private int getHighest(){}   
private int contains(int priority){}  
private int getHighest(){}

private int contains(int priority){}

     private int getHighest(){}方法是用来取得队列中优先权最大的元素的数组索引位  置。


  private int contains(int priority){}方法是用来查找队列中是否存在指定优先  权。如果存在,返回优先权所在的数组索引位置,如果不存在,则返回-1。

三个公有方法: 

   Java代码   

      public Object getFront(){}   
      public void insert(Object item, int priority){}   
      public Object removeFront(){}  
public Object getFront(){}

public void insert(Object item, int priority){}

public Object removeFront(){}

      public Object getFront(){}方法是用来取得优先权最大的元素的。


     public void insert(Object item, int priority){}方法是用来往队列中添加元素  的。衡量优先权的标准可以很多,这里是直接要求用户在存储元素的时候存储优先权。这个  队列也还没有考虑队列满了以后扩充的情况,所以如果满了会报错。在插入元素时,先要查  看这个元素所对应的优先权是否已经存在,如果已经存在了,那就直接挂到相应数组索引位  置的链表下面。如果不存在,则存放在一个还没有存放值的数组位置中。如果加入元素成  功,要检查是否比原来最大的优先权还要大,如果是,则把highest标记为这个新插入元素  的索引位置。

     public Object removeFront(){}方法是用来删除优先权最大的元素的。删除成功时,  会返回被删除的元素值,否则返回null。删除优先权最大的元素后,还要查找出新的优先  权最大的值,并且让highest指向这个值的索引位置。



示例代码:


Java代码   

package cn.priorityQueue;    
/**  
 * 这个优先队列是基于数组的。  
 * 实现方法是,用两个数组,一个存放元素的权限,另外一个存放元素的值,两个数组的位置相互对应。  
 * 往这个队列中存储元素,需要放入两个值,一个是元素的优先级值,另外一个是元素的值  
 * @author William Job  
 *  
 */  
public class PriorityQueue01 {   
    //这个数组priority用来表示每个元素的优先权   
    private int[] priority;   
    //这个数组element用来存储每个元素的值   
    private ElementNode[] elements;   
    //这个值highest用来指向最高优先权的元素   
    private int highest = 0;   
    //manyItems用来计数已经存储的元素个数   
    private int manyItems;   
    //PriorityCount用来计数已经存储的优先权个数   
    private int PriotityCount;   
       
    public PriorityQueue01(int initialCapacity){   
        priority = new int[initialCapacity];   
        elements = new ElementNode[initialCapacity];   
        manyItems = 0;   
        PriotityCount = 0;   
    }   
       
    /**  
     * 这个方法是用来取得优先权最大的值的。  
     * @throws IllegalAccessException   
     * @return:返回拥有最大优先权的值  
     */  
    public Object getFront(){   
        if(manyItems == 0){   
            throw new IllegalArgumentException("没有元素!");   
        }   
        return elements[highest].element;   
    }              
    /**  
     * 这个方法用来向队列中添加一个元素  
     * 在这个优先队列的实现中,必须同时给定元素的值和元素的优先值  
     * @param item:元素的值  
     * @param priority:元素的优先值,必须大于0  
     * @throws Exception   
     */  
    public void insert(Object item, int priority){   
        if(PriotityCount >= this.priority.length){   
            throw new IllegalArgumentException("队列已满");   
        }   
           
        if(priority <= 0){   
            throw new IllegalArgumentException("优先权必须大于0!");   
        }   
        int add = contains(priority);   
        if(add >= 0){   
            ElementNode node = new ElementNode();   
            node.element = item;   
            node.link = elements[add];   
            elements[add] = node;   
            manyItems ++;   
        }   
        else{   
            ElementNode node = new ElementNode();   
            node.element = item;   
            if(this.priority[PriotityCount] == 0){   
                elements[PriotityCount] = node;   
                   
                add = PriotityCount;   
            }   
            else{   
                for(int j = 0; j < this.priority.length; j ++){   
                    if(this.priority[j] == 0){   
                        add = j;   
                    }   
                }   
                elements[add] = node;   
            }   
            this.priority[add] = priority;   
            manyItems ++;                  
            PriotityCount ++;   
        }   
           
        if(this.priority[add] > this.priority[highest]){   
            highest = add;   
        }   
    }   
       
    /**  
     * 这个方法是用来取得队列中优先权最大的元素的  
     * @return:返回优先权最大的元素的索引位置  
     */  
    private int getHighest(){   
        int index = -1;   
        int temp = 0;   
        for(int i = 0; i < priority.length; i ++){   
            if(priority[i] > temp){   
                temp = priority[i];   
                index = i;   
            }   
        }   
        return index;   
    }               
    /**  
     * 这个方法用来查找队列中是否已经存在这个优先权  
     * @param priority:要查找的优先权  
     * @return:如果这个优先权已经存在则返回这个优先权相应的索引位置,如果不存在则返回-1  
     */  
    private int contains(int priority){   
        int index = -1;   
        for(int i = 0; i < PriotityCount; i ++){   
            if(this.priority[i] == priority){   
                index = i;   
            }   
        }   
        return index;   
    }   
       
    /**  
     * 这个方法用来删除优先权最大的元素,同时返回这个元素。  
     * 当删除这个元素后,如果这个索引位置再也没有相应的元素,则这个索引位置的优先权赋值为0  
     * @return:队列中优先权最大的元素  
     */  
    public Object removeFront(){   
        ElementNode temp = elements[highest];   
        if(elements[highest].link != null){   
            elements[highest] = elements[highest].link;   
        }   
        else{   
            elements[highest] = null;   
            priority[highest] = 0;   
            PriotityCount --;   
        }   
        highest = getHighest();   
        manyItems --;   
        return temp.element;   
    }              
}    
package cn.priorityQueue;   
/**  
 * 这个是元素的节点类。  
 * 这个类中有两个属性:  
 * element存放元素的值,link指向下一个节点  
 * @author William Job  
 *  
 */  
public class ElementNode {   
       
    //元素的值   
    public Object element;   
    //指向下一个元素的地址   
    public ElementNode link;   
    public Object getElement() {   
        return element;   
    }   
    public void setElement(Object element) {   
        this.element = element;   
    }   
    public Object getLink() {   
        return link;   
    }   
    public void setLink(ElementNode link) {   
        this.link = link;   
    }              
}  

 

下一篇是 JDK实现的优先队列PriorityQueue研究

http://luozhong915127.iteye.com/blog/1852306 

  • 大小: 17.7 KB
3
2
分享到:
评论
1 楼 luozhong915127 2013-04-24  
什么意思,踩别人连个意见都不给。

相关推荐

    数据结构与算法经典问题解析-Java语言描述

    本书强调问题及其分析,而非理论阐述,共分为21章,讲述了基本概念、递归和回溯、链表、栈、队列、树、优先队列和堆、并查集DAT、图算法、排序、查找、选择算法(中位数)、符号表、散列、字符串算法、算法设计技术...

    C语言实例解析精粹(第二版) 光盘代码

    C语言实例解析精粹(第二版) 光盘代码 本文件包括以下内容: ※ 1、文件说明 ※ 2、源码操作说明 ※ 3、光盘目录清单 ◎ 源码操作说明 源代码使用方法是(以实例1为例): 将该实例的源码,比如实例1的1.c文件(可以...

    基于c++及linux网络编程的web服务器源码.zip

    实现了一个小根堆的定时器及时剔除超时请求,使用了STL的优先队列来管理定时器 解析了HTTP的get、post请求,支持长短连接 线程的工作分配为: 主线程负责等待epoll中的事件,并把到来的事件放进任务队列,在每次...

    c语言实例解析——数据结构篇(42-74)

    047 堆排序 048 归并排序 049 基数排序 050 二叉搜索树操作 051 二项式系数递归 052 背包问题 053 顺序表插入和删除 054 链表操作(1) 055 链表操作(2) 056 单链表就地逆置 057 运动会分数统计 058 双...

    C语言实例解析精粹

    第三部分 数值计算与趣味数学篇 075 绘制余弦曲线和直线的迭加 076 计算高次方数的尾数 077 打鱼还是晒网 078 怎样存钱以获取最大利息 079 阿姆斯特朗数 080 亲密数 081 自守数 082 具有abcd=(ab+cd)2性质的...

    考研-数据结构-殷人昆.zip

    3.2 栈和队列的存储结构、算法与应用 56 3.2.1 本章所涉及的结构体定义 56 3.2.2 顺序栈 57 3.2.3 链栈 59 3.2.4 栈的应用 60 3.2.5 顺序队 64 3.2.6 链队 66 3.3 抽象数据类型 69 ▲真题仿造 71 真题仿造答案与讲解...

    siftjava源码-MaoDataStructures:Arrays(数组)、Stacks(栈)、Queues(队列)、LinkedList

    Arrays(数组)、Stacks(栈)、Queues(队列)、LinkedList(链表)、Recursion(递归思想)、BinarySearchTree(二分搜索树)、Set(集合)、Map(映射)、Heap(堆)、PriorityQueue(优先队列)、SegmentTree(线段树)、Trie(字典树)...

    谭浩强C语言程序设计,C++程序设计,严蔚敏数据结构,高一凡数据结构算法分析与实现.rar

    *5.6 C++处理字符串的方法——字符串类与字符串变量 5.6.1 字符串变量的定义和引用 5.6.2 字符串变量的运算 5.6.3 字符串数组 5.6.4 字符串运算举例 习题 第6章 指针 6.1 指针的概念 6.2 变量与指针 6.2.1 定义...

    leetcode分类-leetcode:练习leetcode题目,提高编程能力

    栈与队列 哈希表 堆:最大堆 / 最小堆 树与图:最近公共祖先、并查集 字符串:前缀树(字典树) / 后缀树 传送门 leetcode 经典题目的解析 这里仅列举具有代表性题目,并不是全部题目 简单难度 中等难度 困难难度 ...

    谭浩强C语言程序设计,C++程序设计,严蔚敏数据结构,高一凡数据结构算法分析与实现.rar )

    *5.6 C++处理字符串的方法——字符串类与字符串变量 5.6.1 字符串变量的定义和引用 5.6.2 字符串变量的运算 5.6.3 字符串数组 5.6.4 字符串运算举例 习题 第6章 指针 6.1 指针的概念 6.2 变量与指针 6.2.1 定义...

    leetcode答案-leetcode:记录自己的算法成长

    栈与队列 哈希表 堆:最大堆 / 最小堆 树与图:最近公共祖先、并查集 字符串:前缀树(字典树) / 后缀树 如何正确高效地使用LeetCode? 基本步骤 汇总经典题型,分门别类去刷; 标出难度,给出解析过程; 反复...

    C 语言实例解析精粹(第二版)(书+盘)

    第三部分 数值计算与趣味数学篇 075 绘制余弦曲线和直线的迭加 076 计算高次方数的尾数 077 打鱼还是晒网 078 怎样存钱以获取最大利息 079 阿姆斯特朗数 080 亲密数 081 自守数 082 具有abcd=(ab+cd)2性质的...

    lrucacheleetcode-leetcode:我的leetcode解决方案

    解析 数学 常见的 组合号 基数 少量 几何学 大批 常见的 改编 滑动窗口 哈希表 链表 子集 两个指针 种类 字首 堆栈/队列 堆 单调(单调栈) 哈希表 放 少量 堆 最小堆 快速删除 链表 常见的 ./topics/linked-list/...

    《算法》中文版,Robert Sedgewick,塞奇威克

    2.4 优先队列 2.4.1 API 2.4.2 初级实现 2.4.3 堆的定义 2.4.4 堆的算法 2.4.5 堆排序 2.5 应用 2.5.1 将各种数据排序 2.5.2 我应该使用哪种排序算法 2.5.3 问题的归约 2.5.4 排序应用一览 第3章 查找 ...

    算法,4th,塞奇威克 (Robert Sedgewick)韦恩 (Kevin Wayne), 谢路云 译.azw3

    2.4 优先队列 2.4.1 API 2.4.2 初级实现 2.4.3 堆的定义 2.4.4 堆的算法 2.4.5 堆排序 2.5 应用 2.5.1 将各种数据排序 2.5.2 我应该使用哪种排序算法 2.5.3 问题的归约 2.5.4 排序应用一览 第3章 查找 ...

    Objective-C的MKNetworkKit开发框架解析

    在集成二者的优秀特性之外,还增加了一堆新的功能。尤其是,相比起其它框架,它能让你更轻松地编写代码。它让你彻底远离那些恶心的网络代码。 特点 超轻量级框架 整个框架只有 2 个类和一些类别方法。因此,它的使用...

    leetcode中文版-leetcode:leetcode

    html解析器 图形 普里姆 迪杰斯特拉 力码 3sum 3sum_closest 4sum 添加二进制 添加数字 添加字符串 add_two_numbers balance_binary_tree best_time_to_buy_and_sell_stock best_time_to_buy_and_sell_stock_II ...

    leetcode中文版-cabbird:一组用python编写的算法

    html解析器 图形 普里姆 迪杰斯特拉 力码 3sum 3sum_closest 4sum 添加二进制 添加数字 添加字符串 add_two_numbers balance_binary_tree best_time_to_buy_and_sell_stock best_time_to_buy_and_sell_stock_II ...

    computer_science:大多数公共数据结构和算法的实现

    计算机科学数据结构和算法 首先,我将使用 javascript 实现所有内容:nodejs、gulp、mocha 和其他 javascript 工具。... 实施的: 堆 队列 二叉树 计划: 链表 ...优先队列 二叉搜索树 AVL树 解析树

Global site tag (gtag.js) - Google Analytics