写在之前
1.自定义实现采用数组作为内部数据结构
2.内部数组通过grow方法进行扩容,每次只是简单的扩展为原来的2倍
3.集中实现方式的主要区别在于siftDown方法
4.以下给出关键代码,更多详细信息请看附件源码
实现方式一(递归实现)
关键代码:
@Override protected void siftDown(int index) { int len = totalCount - 1; int left = left(index); int right = right(index); if(left > len) { return; } int currentMin = left; if(right <= len && arr[currentMin] > arr[right]) { currentMin = right; } if(arr[currentMin] < arr[index]) { swap(arr, currentMin, index); siftDown(currentMin); } }
实现方式二(循环实现)
关键代码:
@Override protected void siftDown(int index) { int len = totalCount - 1; while(left(index) <= len) { int left = left(index); int right = right(index); if(left > len) { break; } int currentMin = left; if(right <= len && arr[currentMin] > arr[right]) { currentMin = right; } if(arr[currentMin] >= arr[index]) { break; } swap(arr, currentMin, index); index = currentMin; } }
实现方式三(直接构建堆)
关键代码:
@Override protected void siftDown(int index) { int len = totalCount - 1; while(left(index) <= len) { int left = left(index); int right = right(index); if(left > len) { break; } int currentMin = left; if(right <= len && arr[currentMin] > arr[right]) { currentMin = right; } if(arr[currentMin] < arr[index]) { swap(arr, currentMin, index); } //进入下一个非叶子节点 index++; } }
实现方式四(JDK中的实现)
1.siftUp方法:
protected void siftUp(int k, int x) { while (k > 0) { int parent = parent(k); int e = arr[parent]; if (x >= e) break; arr[k] = e; k = parent; } arr[k] = x; }
2.siftDown方法:
/** * 指定index位置的值为x,并为x在堆中找到合适位置 * @param index * @param x */ private void siftDown(int index, int x) { int half = totalCount >>> 1; while (index < half) { int currentMin = left(index); int right = right(index); if (right < totalCount && arr[currentMin] > arr[right]) currentMin = right; if (x <= arr[currentMin]) break; //将index位置设置为最小节点值 arr[index] = arr[currentMin]; //迭代 index = currentMin; } //将最终值放入合适位置 arr[index] = x; }
其他的一下关键方法
1.siftUp方法:
@Override protected void siftUp(int index) { int parent = parent(index); while(index > 0 && arr[index] < arr[parent]) { swap(arr, index, parent); index = parent; parent = parent(index); } }
2.add方法:
@Override public boolean add(int ele) { if(totalCount == arr.length) { //扩容 grow(); } int i = totalCount; arr[i] = ele; if(totalCount == 1) { return true; } //调整元素位置确保为小根堆 siftUp(i); totalCount++; return true; }
3.poll方法:
@Override public int poll() { int result = arr[0]; arr[0] = arr[--totalCount]; siftDown(0); return result; }
5.remove方法:
@Override public int remove(int ele) { //内部数据为空 if(totalCount < 1) { return -1; } //计算元素位置 int index = indexOf(ele); if(index < 0) { return -1; } return removeAt(index); }
6.removeAt方法:
@Override protected int removeAt(int idx) { if(idx < 0 || idx >= totalCount) { return -1; } int result = arr[idx]; //将删除元素与最后一个元素交换位置 if(idx != totalCount -1) { arr[idx] = arr[totalCount - 1]; } //位置交换之后队列长度减一 totalCount--; //如果队列长度大于1,而且删除的元素位置不在队尾则重新调整堆 if(totalCount > 1 && idx != totalCount) { siftDown(idx); } return result; }
相关推荐
本文将深入探讨优先级队列的概念、实现方式以及如何在实际编程中使用。 首先,理解二叉堆是理解优先级队列的关键。二叉堆分为最大堆和最小堆,最大堆的每个父节点的值都大于或等于其子节点的值,而最小堆则相反,每...
在C++ STL中,`priority_queue`是一个标准模板库,提供了优先级队列的实现。 然后是**双端队列(deque,Double Ended Queue)**,它允许在队列的两端进行入队和出队操作。双端队列常用于栈的功能,如回溯算法,或者...
1. **创建优先级队列**:可以使用`PriorityBlockingQueue`来模拟不同优先级的队列,通过自定义比较器来确定优先级。 2. **时间片管理**:通过`ScheduledExecutorService`来定时检查当前运行的进程是否超时,如果超时...
优先级队列在Java中通过`java.util.PriorityQueue`类实现,这个类是一个无界并发容器,它不保证队列的元素顺序,而是基于最小堆的数据结构来维护元素的顺序,使得每次删除元素时都是当前队列中优先级最高的元素。...
Java实现的基于JMS(Java Message Service)协议的消息队列中间件是一种用于应用程序间异步通信的重要技术。消息队列允许应用程序将消息发送到队列而不必等待接收方的响应,提高了系统的可扩展性和容错性。JMS是Java...
3. **线程公平性**:在某些Java并发框架,如`java.util.concurrent`包中的`ThreadPoolExecutor`,可以配置为优先级队列,这样高优先级的线程会被优先处理,但这仍然取决于工作线程的数量和其他正在运行的任务。...
时间片轮转调度算法是一种多任务调度方式,它的基本思想是将所有就绪进程放入一个队列中,每次选择队首进程执行,但只给它一定的时间片(通常很短)来运行。当时间片用完,进程会被暂停,放回队尾,然后选择下一个...
2. **队列实现**:接着可能会讲解几种具体的阻塞队列实现,比如`ArrayBlockingQueue`是基于数组的有界队列,`LinkedBlockingQueue`基于链表,以及`PriorityBlockingQueue`是无界的优先级队列,它们各自的特点和适用...
Java提供了几种不同的垃圾收集器,如Serial、Parallel、Concurrent Mark Sweep (CMS) 和G1等,它们各有优缺点,适用于不同的场景。例如,Serial GC适合小型应用,而CMS和G1则更适合大型并发环境。 此外,Java还提供...
5. **多级反馈队列调度**:结合了前面几种策略,设置多个优先级队列,低优先级队列的进程如果在一定时间内得不到服务,则提升其优先级。Java实现时需要维护多个队列,并根据条件动态调整进程所在队列。 实现这些...
优先队列是一种特殊的队列,其中元素按照优先级顺序进行排列。在计算机科学中,它是一种数据结构,常用于处理需要快速访问...通过理解和应用这些知识,我们可以设计和实现高效的优先级队列系统,用于解决各种实际问题。
在Java中实现哈夫曼编码涉及到几个关键步骤: 1. **构建哈夫曼树**: - 首先,我们需要一个表示二叉树节点的数据结构。在这个例子中,定义了一个名为`HuffmanTree33`的类,包含了左右子节点、权值和对应编码属性。...
队列技术主要有以下几种: 1. **先进先出(FIFO)**:传统的队列管理方式,数据包按照到达的顺序进行排队和转发。这种简单的方法不提供任何优先级控制,因此对于需要QOS保证的应用效果较差。 2. **优先级队列(PQ...
在Java中实现这样的调度程序,开发者可能使用了线程的概念。Java的`Thread`类和`Runnable`接口允许创建并发执行的任务。通过定义`run()`方法,我们可以指定线程的行为。为了实现FIFO和时间片轮转,可能需要维护一个...
5. **队列数据结构**:为了实现多级队列,可能需要使用Java的`Queue`接口,例如`LinkedList`或`ArrayDeque`,来存储和管理线程。 6. **状态管理**:每个线程需要有一个状态表示(如新建、就绪、运行、阻塞、结束等...
Android提供了几种不同的拒绝策略,如丢弃最旧的任务、抛出异常等。 4. 管理器(ThreadPoolExecutor):负责线程池的生命周期管理,如初始化、扩展、收缩以及关闭线程池。 任务队列(Task Queue)是线程池的重要...
在实际的Java实现中,可能需要维护一个根据寻道距离排序的优先级队列。虽然SSTF可以显著减少平均寻道时间,但它可能出现饥饿问题,即某些远距离的请求会被连续多次地推迟,导致系统响应时间变长。 3. **扫描(SCAN...
5. **多级反馈队列(MLFQ)**:结合了FCFS、SJF和RR,设置多个队列,不同队列的时间片长度不同,新进程进入最高优先级队列,若无法在当前时间片内完成,降入下一个队列。MLFQ兼顾了各种类型进程的需求,较为灵活。 ...
实现高优先级优先调度算法通常包括以下几个步骤: 1. **初始化**:系统启动时,为所有进程分配优先级。这可以通过多种方式实现,比如基于进程类型、内存需求、等待时间等标准。 2. **进程调度**:当处理器空闲时,...