`
128kj
  • 浏览: 601609 次
  • 来自: ...
社区版块
存档分类
最新评论

用堆实现简单的优先队列(JAVA)

阅读更多
   优先队列,顾名思义,就是一种根据一定优先级存储和取出数据的队列。它可以说是队列和排序的完美结合体,不仅可以存储数据,还可以将这些数据按照我们设定的规则进行排序。
优先队列主要方法:
void add(Object o);//进队
void offer(Object o);//进队
Object poll();//出队
Object peek();//查看队列首元素
boolean isEmpty();
int size();

   在下面例子中用基于数组的堆实现优先队列,即堆中的元素保存在一个数组中。堆是一种二叉树,所遵守的唯一规律为:所有的子节点都要大于(小于)父节点。而这个数组元素的保存也是按照一定规律的:如果父结点的位置为n,那么,其对应的左右子结点的位置分别是2n+1和2n+2。

堆有两个很基本的操作:
增加一个节点,直接加在最后,然后用重新调整堆(参看http://128kj.iteye.com/blog/1728555)

删除一个节点,则把要删除的节点与最后节点交换,然后删除交换后的节点(既最后一个点),然后重新调整堆.

class  PriorityQueue {

        protected Comparator comparator;
        final static int ROOT_INDEX = 0;
        final static int PRE_ROOT_INDEX = ROOT_INDEX - 1;

        List heap;//存放队列元素的堆

        public PriorityQueue() {
                heap = new ArrayList();
        }

        public PriorityQueue(Comparator c) {
                heap = new ArrayList();
                comparator = c;
        }

       
        public void add(Object o) {
                heap.add(o);//在最后增加一个元素
                int index = heap.size() - 1;//最后一个元素的索引
                while (index > ROOT_INDEX) {//在堆中加一个元素后,调整堆使其再成为一个堆
                        index = stepUpHeap(index);//上浮
                }
        }

        public void offer(Object o){
              add(o);
        }

        protected int stepUpHeap(int index) {
          int parentIndex = parent(index);//获取父节点的索引
          Object element = heap.get(index);
          Object parent  = heap.get(parentIndex);
          if (compare(parent, element) > 0) { //父节点大于儿子节点,交换
                heap.set(parentIndex, element);
                heap.set(index, parent);
                return parentIndex;  // 跳到父索引
           } else   
                return ROOT_INDEX; //不需要交换
        }

       //比较器
        protected int compare(Object element, Object other) {
           if (comparator == null) {
                 Comparable e = (Comparable) element;
                 Comparable o = (Comparable) other;
                 return e.compareTo(o);
            } else
                  return comparator.compare(element, other);
        }

        
        protected int parent(int index) {
          return (index - PRE_ROOT_INDEX) / 2 + PRE_ROOT_INDEX;
        }

        public String toString() {
                return heap.toString();
        }

       
        public boolean isEmpty() {
                return heap.isEmpty();
        }

      
        public int size() {
                return heap.size();
        }
         
        public Object peek() throws RuntimeException{
          if (isEmpty())
               throw new RuntimeException();
           return heap.get(0);
         }
      
        public Object poll() throws RuntimeException{//取优先队列头元素
            if (isEmpty())
               throw new RuntimeException();

            int index = heap.size() - 1;//最后一个元素的索引
            Object least;
            if(index==0){
               least = heap.get(index);
               heap.remove(index);
            }
            else{
               Object element = heap.get(index);//取最后一个元素
               least  = heap.get(ROOT_INDEX);//取堆的根元素
               heap.set(ROOT_INDEX, element);//交换这两个元素
               heap.set(index, least);
               heap.remove(index);//删除最后一个元素
               stepDownHeap(ROOT_INDEX);//下沉调整,使之再次成为堆
            }
                return least;
        }

                   
        public void stepDownHeap(int index){
                int p = index;
                int c = 2*p + 1;//左子节点
                Object temp = heap.get(p);//
                while(c<heap.size()){
         if(c+1<heap.size() && compare(heap.get(c+1),heap.get(c))<0)//右节点比左节点小
                                c = c + 1;//取两个儿子节点中小的一个
                        if(compare(temp,heap.get(c))<=0)//不需要调整了
                                break;
                        else {
                             heap.set(p,heap.get(c));//较小的儿子节点上浮
                                p = c;
                                c = 2*p + 1;//继续调整
                       }
                }
                heap.set(p,temp);//最后要将temp放到p
        }
}




测试:
import java.util.Comparator;
public class PQTest {
  
 public static void main(String[] args) {

 Comparator c=comparableComparator();
   PriorityQueue pq=new PriorityQueue(c);
   pq.add(2);
   pq.add(101);
   pq.add(1);
   System.out.println(pq.poll());
   System.out.println(pq.peek());
 }

 static Comparator comparableComparator() {
  return new Comparator() {
   public int compare(Object x, Object y) {
    return ((Comparable) x).compareTo(y);
   }
  };
 }
}

运行:

D:\ex>java  PQTest
1
2
下载源码
分享到:
评论

相关推荐

    用数组实现的优先队列(JAVA)

    在Java中,我们可以使用`java.util.PriorityQueue`类来实现优先队列,但这里我们关注的是用数组实现的方法。 2. **数组实现的基本思想** 数组实现优先队列的核心思想是维护一个最小堆(最小堆是堆数据结构的一种,...

    Java基于堆结构实现优先队列功能示例

    该示例程序主要介绍了Java基于堆结构实现优先队列功能的简单定义与使用方法,并提供了实例形式的分析。 知识点一: 堆结构是什么? 堆结构是一种特殊的树形结构,它满足以下两个性质:(1)堆结构是一棵完全二叉树...

    JAVA中的优先队列与堆(POJ 2442)

    Java中的`java.util.PriorityQueue`类实现了优先队列接口,它基于二叉堆实现。 二叉堆是一种完全二叉树,可以分为两种类型:最大堆和最小堆。最大堆中每个节点的值都大于或等于其子节点的值,而最小堆则相反,每个...

    Java Methods-Heaps and Priority Queues.ppt

    二叉堆是一种简单的堆实现方式,它使用了数组来存储数据。斐波那契堆是一种高效的堆实现方式,它使用了斐波那契数列来确定节点的高度。 五、优先队列的应用 优先队列有很多实践应用,例如: * 任务调度:优先队列...

    优先级队列(堆实现)

    例如,我们可以用优先级队列来实现一个简单的任务调度器,优先处理优先级高的任务。 总之,`PriorityQueue`通过堆数据结构提供了高效、灵活的优先级管理功能。在理解和使用过程中,应充分考虑其特性,以便在需要...

    java 栈和队列的小例子

    Java中可以使用LinkedList、ArrayList或PriorityQueue来实现队列,其中LinkedList和ArrayList适用于普通队列,而PriorityQueue则用于优先级队列。以下是一个使用LinkedList实现的队列示例: ```java import java....

    java 实现二叉排序树 堆

    堆是一种特殊的树形数据结构,通常用于实现优先队列。在Java中,我们可以使用`PriorityQueue`类来实现堆。堆分为大顶堆(父节点的值大于或等于其子节点的值)和小顶堆(父节点的值小于或等于其子节点的值)。`...

    手撸一个优先队列(csdn)————程序.pdf

    在Java中,`java.util.PriorityQueue`是内置的优先队列实现,但这里我们将探讨如何手动实现一个简单的优先队列。 首先,我们需要理解优先队列的核心功能。这个手动实现的优先队列将具备以下特性: 1. **泛型支持**...

    最佳优先搜索算法介绍和java代码实现

    4. **效率提升**:可以使用堆数据结构(如Java的`PriorityQueue`)来实现优先队列,提高算法执行效率。 然而,最佳优先搜索算法也存在一些缺点: 1. **局部最优解**:在某些复杂问题中,算法可能会陷入局部最优解...

    队列 堆 栈 堆栈的区别

    堆常用于实现优先队列。 2. **作为内存管理的堆:**指在程序运行期间动态分配的内存空间。堆上的内存分配通常通过函数如 `malloc`(C语言)、`new`(C++和Java)来进行。堆内存由操作系统管理,并且通常比栈内存...

    基于Java实现的Dijkstra最短路径寻径的实现

    它维护一个优先队列(通常使用二叉堆实现),用于存储未访问过的节点,并根据当前已知的最短距离进行排序。每次从队列中取出距离起点最近的节点,更新与其相邻的节点的距离,然后将这些节点重新插入队列。 1. **...

    用Java实现的迪杰斯特拉最短路径算法

    2. **优先队列(Priority Queue)**:在Java中,我们可以使用`java.util.PriorityQueue`来实现最小堆,用于存储待访问的节点。优先队列能保证每次取出的元素是最小的,这对于不断寻找当前已知最短路径至关重要。 3....

    Java模拟操作系统实验之四种进程调度算法实现(FCFS,SJF,RR,HRN)

    在进行上述算法实现时,Java的集合框架(如ArrayList、LinkedList)和数据结构(如堆、优先队列)将发挥重要作用。同时,需要注意的是,模拟过程中应考虑进程的创建、唤醒、阻塞和结束等状态转换,以及可能的进程...

    java-数据结构代码实现

    6. **树**:树是一种非线性数据结构,包括二叉树、平衡二叉树(如AVL树、红黑树)、堆(如优先队列)等。Java中的`TreeMap`和`TreeSet`基于红黑树实现,你可以在代码中找到关于树操作的实现。 7. **图**:图数据...

    Dijkstra搜索算法介绍和java代码简单实现

    这个算法的核心思想是逐步扩展从起点到其他节点的最短路径,通过维护一个距离数组来跟踪已知的最短距离,并利用优先队列(通常使用堆实现)来选择下一个距离最短的节点进行处理。 算法的主要步骤如下: 1. 初始化...

    数据结构关于栈和队列的实现源代码

    - **顺序队列**:使用数组实现,当队列满时,需要进行队列的扩容;当队列空时,需要判断是否真的为空。 - **循环队列**:对数组进行逻辑上的循环,避免了顺序队列的扩容问题。 - **链式队列**:使用链表节点存储...

    java实现的内存分配

    在Java编程语言中,内存管理是一项关键任务,它涉及到如何有效地分配、使用和释放内存资源。内存分配通常由Java虚拟机(JVM)自动进行,但程序员也可以通过理解和利用特定的策略来优化这一过程。本篇文章将深入探讨...

    Dijkstra迪杰斯特拉算法JAVA

    在Java中实现Dijkstra算法,通常会使用`PriorityQueue`作为优先队列,`LinkedList`或`ArrayList`来表示邻接表结构,以便快速访问和修改节点信息。以下是一个简单的Java代码实现框架: ```java import java.util.*; ...

    先来先服务、短进程优先

    在Java中实现SJF,需要维护一个数据结构(如优先级队列或堆)来存储进程,并根据它们的预期运行时间排序。每次需要选择下一个进程时,都会选取当前预期运行时间最短的进程。 **Java实现** 在提供的压缩包文件中,...

Global site tag (gtag.js) - Google Analytics