循环队列(Circular Queue)

循环队列是一种线性数据结构,其操作表现基于 FIFO(先进先出)原则并且队尾被连接在队首之后以形成一个循环。它也被称为“环形缓冲器”

循环队列的一个好处是我们可以利用这个队列之前用过的空间。在一个普通队列里,一旦一个队列满了,我们就不能插入下一个元素,即使在队列前面仍有空间。但是使用循环队列,我们能使用这些空间去存储新的值。

Properties

  • de_queue O(1)
  • en_queue O(1)
  1. use std::{
  2. alloc::{self, Layout},
  3. ptr,
  4. };
  5. pub struct CircularQueue<T> {
  6. write_index: usize,
  7. read_index: usize,
  8. cap: usize,
  9. len: usize,
  10. data: Box<[T]>,
  11. }
  12. impl<T> CircularQueue<T> {
  13. pub fn new(cap: usize) -> Self {
  14. let data = unsafe {
  15. let data_ptr = alloc::alloc(Layout::array::<T>(cap).unwrap()) as *mut T;
  16. Box::from_raw(ptr::slice_from_raw_parts_mut(data_ptr, cap))
  17. };
  18. Self {
  19. write_index: 0,
  20. read_index: 0,
  21. cap,
  22. len: 0,
  23. data,
  24. }
  25. }
  26. /**
  27. * add value to CircularQueue
  28. * return true if success, false if queue is full
  29. */
  30. pub fn en_queue(&mut self, value: T) -> bool {
  31. if self.is_full() {
  32. false
  33. } else {
  34. self.data[self.write_index] = value;
  35. self.write_index = (self.write_index + 1) % self.cap;
  36. self.len += 1;
  37. true
  38. }
  39. }
  40. /**
  41. * remove value from CircularQueue
  42. * return true if success, false if queue is full
  43. */
  44. pub fn de_queue(&mut self) -> bool {
  45. if self.is_empty() {
  46. false
  47. } else {
  48. self.read_index = (self.read_index + 1) % self.cap;
  49. self.len -= 1;
  50. true
  51. }
  52. }
  53. /**
  54. * get front value
  55. */
  56. pub fn front(&self) -> Option<&T> {
  57. if self.is_empty() {
  58. None
  59. } else {
  60. Some(&self.data[self.read_index])
  61. }
  62. }
  63. /**
  64. * get tail value
  65. */
  66. pub fn rear(&self) -> Option<&T> {
  67. if self.is_empty() {
  68. None
  69. } else if self.write_index == 0 {
  70. Some(&self.data[self.cap - 1])
  71. } else {
  72. Some(&self.data[self.write_index - 1])
  73. }
  74. }
  75. pub fn is_empty(&self) -> bool {
  76. self.len == 0
  77. }
  78. pub fn is_full(&self) -> bool {
  79. self.cap == self.len
  80. }
  81. }
  82. #[cfg(test)]
  83. mod tests {
  84. use std::result;
  85. use super::*;
  86. #[test]
  87. fn test_en_queue() {
  88. let mut circular_queue = CircularQueue::new(100);
  89. for i in 0..100 {
  90. let result = circular_queue.en_queue(i);
  91. assert!(result);
  92. }
  93. let result = circular_queue.en_queue(100);
  94. assert!(!result);
  95. }
  96. #[test]
  97. fn test_de_queue() {
  98. let mut circular_queue = CircularQueue::new(100);
  99. for i in 0..200 {
  100. circular_queue.en_queue(i);
  101. }
  102. for _ in 0..100 {
  103. let result = circular_queue.de_queue();
  104. assert!(result);
  105. }
  106. let result = circular_queue.de_queue();
  107. assert!(!result);
  108. }
  109. #[test]
  110. fn test_circular_queue_order() {
  111. let mut circular_queue = CircularQueue::new(3);
  112. for i in 1..4 {
  113. circular_queue.en_queue(i);
  114. }
  115. circular_queue.en_queue(4);
  116. let result = circular_queue.rear();
  117. assert_eq!(result, Some(&3));
  118. assert!(circular_queue.is_full());
  119. circular_queue.de_queue();
  120. circular_queue.en_queue(4);
  121. let result = circular_queue.front();
  122. assert_eq!(result, Some(&2));
  123. let result = circular_queue.rear();
  124. assert_eq!(result, Some(&4))
  125. }
  126. }