当前位置: 首页 > 文档资料 > RustPrimer 中文版 >

常用数据结构实现 - 优先队列

优质
小牛编辑
135浏览
2023-12-01

简介

普通的队列是一种先进先出的数据结构,元素在队列尾追加,而从队列头删除。在优先队列中,元素被赋予优先级。当访问元素时,具有最高优先级的元素最先删除。优先队列具有最高级先出 (largest-in,first-out)的行为特征。

优先队列是0个或多个元素的集合,每个元素都有一个优先权或值,对优先队列执行的操作有:

  1. 查找;
  2. 插入一个新元素;
  3. 删除。

在最小优先队列(min priority queue)中,查找操作用来搜索优先权最小的元素,删除操作用来删除该元素;对于最大优先队列(max priority queue),查找操作用来搜索优先权最大的元素,删除操作用来删除该元素。优先权队列中的元素可以有相同的优先权,查找与删除操作可根据任意优先权进行。

优先队列的实现:

首先定义 PriorityQueue 结构体

  1. #[derive(Debug)]
  2. struct PriorityQueue<T> where T: PartialOrd + Clone {
  3. pq: Vec<T>
  4. }

第二行的where T: PartialOrd + Clone指的是 PriorityQueue 存储的泛型 T 是满足 PartialOrdClone trait 约束的,意味着泛型 T 是可排序和克隆的。

后面是一些基本的方法实现,比较简单,就直接看代码吧。这个优先队列是基于Vec实现的,有O(1)的插入和O(n)的最大/最小值出列。

  1. impl<T> PriorityQueue<T> where T: PartialOrd + Clone {
  2. fn new() -> PriorityQueue<T> {
  3. PriorityQueue { pq: Vec::new() }
  4. }
  5. fn len(&self) -> usize {
  6. self.pq.len()
  7. }
  8. fn is_empty(&self) -> bool {
  9. self.pq.len() == 0
  10. }
  11. fn insert(&mut self, value: T) {
  12. self.pq.push(value);
  13. }
  14. fn max(&self) -> Option<T> {
  15. if self.is_empty() { return None }
  16. let max = self.max_index();
  17. Some(self.pq[max].clone())
  18. }
  19. fn min(&self) -> Option<T> {
  20. if self.is_empty() { return None }
  21. let min = self.min_index();
  22. Some(self.pq[min].clone())
  23. }
  24. fn delete_max(&mut self) -> Option<T> {
  25. if self.is_empty() { return None; }
  26. let max = self.max_index();
  27. Some(self.pq.remove(max).clone())
  28. }
  29. fn delete_min(&mut self) -> Option<T> {
  30. if self.is_empty() { return None; }
  31. let min = self.min_index();
  32. Some(self.pq.remove(min).clone())
  33. }
  34. fn max_index(&self) -> usize {
  35. let mut max = 0;
  36. for i in 1..self.pq.len() - 1 {
  37. if self.pq[max] < self.pq[i] {
  38. max = i;
  39. }
  40. }
  41. max
  42. }
  43. fn min_index(&self) -> usize {
  44. let mut min = 0;
  45. for i in 0..self.pq.len() - 1 {
  46. if self.pq[i] < self.pq[i + 1] {
  47. min = i;
  48. }
  49. }
  50. min
  51. }
  52. }

测试代码:

  1. fn test_keep_min() {
  2. let mut pq = PriorityQueue::new();
  3. pq.insert(3);
  4. pq.insert(2);
  5. pq.insert(1);
  6. pq.insert(4);
  7. assert!(pq.min().unwrap() == 1);
  8. }
  9. fn test_keep_max() {
  10. let mut pq = PriorityQueue::new();
  11. pq.insert(2);
  12. pq.insert(4);
  13. pq.insert(1);
  14. pq.insert(3);
  15. assert!(pq.max().unwrap() == 4);
  16. }
  17. fn test_is_empty() {
  18. let mut pq = PriorityQueue::new();
  19. assert!(pq.is_empty());
  20. pq.insert(1);
  21. assert!(!pq.is_empty());
  22. }
  23. fn test_len() {
  24. let mut pq = PriorityQueue::new();
  25. assert!(pq.len() == 0);
  26. pq.insert(2);
  27. pq.insert(4);
  28. pq.insert(1);
  29. assert!(pq.len() == 3);
  30. }
  31. fn test_delete_min() {
  32. let mut pq = PriorityQueue::new();
  33. pq.insert(3);
  34. pq.insert(2);
  35. pq.insert(1);
  36. pq.insert(4);
  37. assert!(pq.len() == 4);
  38. assert!(pq.delete_min().unwrap() == 1);
  39. assert!(pq.len() == 3);
  40. }
  41. fn test_delete_max() {
  42. let mut pq = PriorityQueue::new();
  43. pq.insert(2);
  44. pq.insert(10);
  45. pq.insert(1);
  46. pq.insert(6);
  47. pq.insert(3);
  48. assert!(pq.len() == 5);
  49. assert!(pq.delete_max().unwrap() == 10);
  50. assert!(pq.len() == 4);
  51. }
  52. fn main() {
  53. test_len();
  54. test_delete_max();
  55. test_delete_min();
  56. test_is_empty();
  57. test_keep_max();
  58. test_keep_min();
  59. }

练习

基于二叉堆实现一个优先队列,以达到O(1)的出列和O(log n)的入列