数据结构之队列(优先队列)
概念
优先队列(Priority Queue)为一种不必遵守队列特性FIFO(先进先出)的有序线性表,其中每个元素都赋予一个优先级(Priority),加入元素时可任意加入,但有最高优先级者(Highest Priority Out First HPOF)则最先输出。
Java
在Java中,PriorityQueue 类实现了这样的一种有序队列。
PriorityQueue 是一个基于优先堆的无界优先队列。堆是一种特殊的树形数据结构,它满足以下两个条件:
- 父节点的值总是大于或等于子节点的值
- 每个节点的左子树和右子树也是一个堆
PriorityQueue 的主要方法包括:
- add(E e):将指定的元素插入此优先队列。
- offer(E e):将指定的元素插入此优先队列。
- remove():获取并移除此队列的头,如果此队列为空,则返回 null 。
- poll(): 获取并移除此队列的头,如果此队列为空,则返回 null 。
- element():获取但不移除此队列的头,如果此队列为空,则抛出一个 NoSuchElementException 异常。
- peek():获取但不移除此队列的头,如果此队列为空,则返回 null 。
创建 PriorityQueue 可传入一个 Comparator 对象,该对象用来对元素进行排序。Comparator 接口中只有一个方法 compare()
,在 PriorityQueue 中决定元素的顺序:
1 | int compare(T o1, T o2) |
该方法返回一个负整数、零或正整数,表示 o1 按照某种特定的顺序小于、等于或大于 o2。
1 import java.util.Comparator; 2 import java.util.PriorityQueue; 3 4 public class PriorityQueueExample { 5 public static void main(String[] args) { 6 // 创建一个自然排序的 PriorityQueue 7 PriorityQueue<Integer> numbers = new PriorityQueue<>(new Comparator<Integer>() { 8 @Override 9 public int compare(Integer o1, Integer o2) { 10 return o1.compareTo(o2); 11 } 12 }); 13 14 // 添加元素 15 numbers.add(4); 16 numbers.add(2); 17 numbers.add(5); 18 numbers.add(1); 19 numbers.add(3); 20 21 System.out.println("Priority Queue: " + numbers); 22 23 // 获取队列头部的元素 24 int peek = numbers.peek(); 25 System.out.println("队列头部的元素是:" + peek); 26 27 // 删除队列头部的元素 28 int poll = numbers.poll(); 29 System.out.println("删除的元素是:" + poll); 30 31 System.out.println("新的 Priority Queue: " + numbers); 32 // 队列中元素的存储顺序,与出队顺序不一定一致 33 while (!numbers.isEmpty()){ 34 // 删除队列头部的元素 35 System.out.println("删除的元素是:" + numbers.poll()); 36 37 } 38 } 39 }
输出:
1 2 3 4 5 6 7 8 | Priority Queue: [ 1 , 2 , 5 , 4 , 3 ] 队列头部的元素是: 1 删除的元素是: 1 新的 Priority Queue: [ 2 , 3 , 5 , 4 ] 删除的元素是: 2 删除的元素是: 3 删除的元素是: 4 删除的元素是: 5 |
Python
在Python中,我们可以使用heapq
模块来实现优先队列。
1 import heapq 2 3 # 初始化一个空堆结构 4 h = [] 5 6 # 加入元素 7 heapq.heappush(h, 5) 8 heapq.heappush(h, 7) 9 heapq.heappush(h, 3) 10 11 # 弹出并返回最小的元素 12 print(heapq.heappop(h)) # 3 13 14 # 查看最小的元素,不弹出 15 print(h[0]) # 5 16 17 # 弹出后打印,以此类推,直到为空 18 while h: 19 print(heapq.heappop(h)) # 5 7
输出:
1 2 3 4 | 1 3 3 5 |
通过heappop方法你会按照从小到大依次取出值。
列表转换堆
1 import heapq 2 3 h = [] 4 # heapq._heapify_max(h) # 将list h 转换为最大堆.最大堆(MaxHeap)根节点的值最大,每个父节点的值都比子节点的值要大 5 heapq.heapify(h) # 将list h 转换为最大堆.最大堆(MaxHeap)根节点的值最大,每个父节点的值都比子节点的值要大 6 7 heapq.heappush(h, 1) 8 heapq.heappush(h, 3) 9 heapq.heappush(h, 5) 10 11 print(heapq.heappop(h)) # 1 12 print(h[0]) # 3 13 14 while h: 15 print(heapq.heappop(h)) # 3 5
输出:
1 2 3 4 | 1 3 3 5 |
Javascript
1 class PriorityQueue { 2 constructor() { 3 this.items = []; 4 } 5 6 enqueue(element) { 7 if (this.isEmpty()) { 8 this.items.push(element); 9 } else { 10 let added = false; 11 for (let i = 0; i < this.items.length; i++) { 12 if (element.priority < this.items[i].priority) { 13 this.items.splice(i, 0, element); 14 added = true; 15 break; 16 }else if(element.priority==undefined && element < this.items[i]){ 17 this.items.splice(i, 0, element); 18 added = true; 19 break; 20 } 21 } 22 if (!added) { 23 this.items.push(element); 24 } 25 } 26 } 27 28 dequeue() { 29 return this.items.shift(); 30 } 31 32 isEmpty() { 33 return this.items.length === 0; 34 } 35 } 36 37 queue =new PriorityQueue() 38 queue.enqueue(2) 39 queue.enqueue(1) 40 queue.enqueue(9) 41 queue.enqueue(8) 42 console.log(queue) 43 while (!queue.isEmpty()){ 44 console.log(queue.dequeue()) 45 }
输出:
1 2 3 4 5 | PriorityQueue { items: [ 1 , 2 , 8 , 9 ] } 1 2 8 9 |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!