原文: https://www.programiz.com/dsa/deque

在本教程中,您将学习什么是双端队列(双端队列)。 另外,您还将找到在 C,C++ ,Java 和 Python 的双端队列上进行不同操作的工作示例。

双端队列是队列的一种,其中元素的插入和删除可以从前面或后面进行。 因此,它不遵循 FIFO 规则(先进先出)。

双端队列 - 图1

双端队列


双端队列的类型

  1. 输入限制双端队列
    在此双端队列中,输入在一端限制,但允许在两端删除。
  2. 输出限制双端队列
    在此双端队列中,输出限制在一个端部,但允许在两端插入。

双端队列操作

下面是循环双端数组实现的双端队列。 在圆形数组中,如果数组已满,我们将从头开始。

但是在线性数组实现中,如果数组已满,则无法插入更多元素。 在下面的每个操作中,如果数组已满,则会引发“溢出消息”。

在执行以下操作之前,请执行以下步骤。

  1. 取大小为n的数组。
  2. 在第一个位置设置两个指针,然后设置front = -1rear = 0

双端队列 - 图2

初始化数组和指针

在前面插入

此操作在前面添加了一个元素。

  1. 检查前面的位置。
    双端队列 - 图3
    检查正面

  2. 如果为front < 1,请重新初始化front = n-1(最后一个索引)。
    双端队列 - 图4
    前端发送

  3. 否则,将front减小 1。

  4. 将新键5添加到array[front]中。
    双端队列 - 图5
    插入键

在后面插入

此操作在后部增加了一个元素。

  1. 检查数组是否已满。
    双端队列 - 图6
    检查完整的

  2. 如果数组已满,请重新初始化rear = 0

  3. 否则,将rear增加 1。
    双端队列 - 图7
    增加后

  4. 将新键5添加到array[rear]中。
    双端队列 - 图8
    插入键

从前面删除

该操作从前面删除一个元素。

  1. 检查数组是否为空。
    双端队列 - 图9
    检查为空

  2. 如果数组为空(即front = -1),则无法执行删除操作(下溢条件)。

  3. 如果双端队列只有一个元素(即front = rear),请设置front = -1rear = -1

  4. 否则,如果front位于末尾(即front = n - 1),则设置转到前front = 0

  5. 否则,front = front + 1
    双端队列 - 图10
    增加前线

从后面删除

此操作从背面删除一个元素。

  1. 检查数组是否为空。
    双端队列 - 图11
    检查为空

  2. 如果数组为空(即front = -1),则无法执行删除操作(下溢条件)。

  3. 如果双端队列只有一个元素(即front = rear),请设置front = -1rear = -1,否则请按照以下步骤操作。

  4. 如果rear在前面(即rear = 0),则设置转到前rear = n - 1

  5. 否则,rear = rear - 1
    双端队列 - 图12
    降低后排

检查空

此操作检查数组是否为空。 如果为front = -1,则双端队列为空。

检查满

此操作检查双端队列是否已满。 如果front = 0rear = n - 1,则双端队列已满。


Python,Java 和 C/C++ 示例

  1. # Deque operations in python
  2. class Deque:
  3. def __init__(self):
  4. self.items = []
  5. def isEmpty(self):
  6. return self.items == []
  7. def addFront(self, item):
  8. self.items.append(item)
  9. def addRear(self, item):
  10. self.items.insert(0, item)
  11. def removeFront(self):
  12. return self.items.pop()
  13. def removeRear(self):
  14. return self.items.pop(0)
  15. def size(self):
  16. return len(self.items)
  17. d = Deque()
  18. print(d.isEmpty())
  19. d.addRear(8)
  20. d.addRear(5)
  21. d.addFront(7)
  22. d.addFront(10)
  23. print(d.size())
  24. print(d.isEmpty())
  25. d.addRear(11)
  26. print(d.removeRear())
  27. print(d.removeFront())
  28. d.addFront(55)
  29. d.addRear(45)
  30. print(d.items)
  1. // Deque operations in Java
  2. class Deque {
  3. static final int MAX = 100;
  4. int arr[];
  5. int front;
  6. int rear;
  7. int size;
  8. public Deque(int size) {
  9. arr = new int[MAX];
  10. front = -1;
  11. rear = 0;
  12. this.size = size;
  13. }
  14. boolean isFull() {
  15. return ((front == 0 && rear == size - 1) || front == rear + 1);
  16. }
  17. boolean isEmpty() {
  18. return (front == -1);
  19. }
  20. void insertfront(int key) {
  21. if (isFull()) {
  22. System.out.println("Overflow");
  23. return;
  24. }
  25. if (front == -1) {
  26. front = 0;
  27. rear = 0;
  28. }
  29. else if (front == 0)
  30. front = size - 1;
  31. else
  32. front = front - 1;
  33. arr[front] = key;
  34. }
  35. void insertrear(int key) {
  36. if (isFull()) {
  37. System.out.println(" Overflow ");
  38. return;
  39. }
  40. if (front == -1) {
  41. front = 0;
  42. rear = 0;
  43. }
  44. else if (rear == size - 1)
  45. rear = 0;
  46. else
  47. rear = rear + 1;
  48. arr[rear] = key;
  49. }
  50. void deletefront() {
  51. if (isEmpty()) {
  52. System.out.println("Queue Underflow\n");
  53. return;
  54. }
  55. // Deque has only one element
  56. if (front == rear) {
  57. front = -1;
  58. rear = -1;
  59. } else if (front == size - 1)
  60. front = 0;
  61. else
  62. front = front + 1;
  63. }
  64. void deleterear() {
  65. if (isEmpty()) {
  66. System.out.println(" Underflow");
  67. return;
  68. }
  69. if (front == rear) {
  70. front = -1;
  71. rear = -1;
  72. } else if (rear == 0)
  73. rear = size - 1;
  74. else
  75. rear = rear - 1;
  76. }
  77. int getFront() {
  78. if (isEmpty()) {
  79. System.out.println(" Underflow");
  80. return -1;
  81. }
  82. return arr[front];
  83. }
  84. int getRear() {
  85. if (isEmpty() || rear < 0) {
  86. System.out.println(" Underflow\n");
  87. return -1;
  88. }
  89. return arr[rear];
  90. }
  91. public static void main(String[] args) {
  92. Deque dq = new Deque(4);
  93. System.out.println("Insert element at rear end : 12 ");
  94. dq.insertrear(12);
  95. System.out.println("insert element at rear end : 14 ");
  96. dq.insertrear(14);
  97. System.out.println("get rear element : " + dq.getRear());
  98. dq.deleterear();
  99. System.out.println("After delete rear element new rear become : " + dq.getRear());
  100. System.out.println("inserting element at front end");
  101. dq.insertfront(13);
  102. System.out.println("get front element: " + dq.getFront());
  103. dq.deletefront();
  104. System.out.println("After delete front element new front become : " + +dq.getFront());
  105. }
  106. }
  1. // Deque operations in C
  2. #include <stdio.h>
  3. #define MAX 10
  4. void addFront(int *, int, int *, int *);
  5. void addRear(int *, int, int *, int *);
  6. int delFront(int *, int *, int *);
  7. int delRear(int *, int *, int *);
  8. void display(int *);
  9. int count(int *);
  10. int main()
  11. {
  12. int arr[MAX];
  13. int front, rear, i, n;
  14. front = rear = -1;
  15. for (i = 0; i < MAX; i++)
  16. arr[i] = 0;
  17. addRear(arr, 5, &front, &rear);
  18. addFront(arr, 12, &front, &rear);
  19. addRear(arr, 11, &front, &rear);
  20. addFront(arr, 5, &front, &rear);
  21. addRear(arr, 6, &front, &rear);
  22. addFront(arr, 8, &front, &rear);
  23. printf("\nElements in a deque: ");
  24. display(arr);
  25. i = delFront(arr, &front, &rear);
  26. printf("\nremoved item: %d", i);
  27. printf("\nElements in a deque after deletion: ");
  28. display(arr);
  29. addRear(arr, 16, &front, &rear);
  30. addRear(arr, 7, &front, &rear);
  31. printf("\nElements in a deque after addition: ");
  32. display(arr);
  33. i = delRear(arr, &front, &rear);
  34. printf("\nremoved item: %d", i);
  35. printf("\nElements in a deque after deletion: ");
  36. display(arr);
  37. n = count(arr);
  38. printf("\nTotal number of elements in deque: %d", n);
  39. }
  40. void addFront(int *arr, int item, int *pfront, int *prear)
  41. {
  42. int i, k, c;
  43. if (*pfront == 0 && *prear == MAX - 1)
  44. {
  45. printf("\nDeque is full.\n");
  46. return;
  47. }
  48. if (*pfront == -1)
  49. {
  50. *pfront = *prear = 0;
  51. arr[*pfront] = item;
  52. return;
  53. }
  54. if (*prear != MAX - 1)
  55. {
  56. c = count(arr);
  57. k = *prear + 1;
  58. for (i = 1; i <= c; i++)
  59. {
  60. arr[k] = arr[k - 1];
  61. k--;
  62. }
  63. arr[k] = item;
  64. *pfront = k;
  65. (*prear)++;
  66. }
  67. else
  68. {
  69. (*pfront)--;
  70. arr[*pfront] = item;
  71. }
  72. }
  73. void addRear(int *arr, int item, int *pfront, int *prear)
  74. {
  75. int i, k;
  76. if (*pfront == 0 && *prear == MAX - 1)
  77. {
  78. printf("\nDeque is full.\n");
  79. return;
  80. }
  81. if (*pfront == -1)
  82. {
  83. *prear = *pfront = 0;
  84. arr[*prear] = item;
  85. return;
  86. }
  87. if (*prear == MAX - 1)
  88. {
  89. k = *pfront - 1;
  90. for (i = *pfront - 1; i < *prear; i++)
  91. {
  92. k = i;
  93. if (k == MAX - 1)
  94. arr[k] = 0;
  95. else
  96. arr[k] = arr[i + 1];
  97. }
  98. (*prear)--;
  99. (*pfront)--;
  100. }
  101. (*prear)++;
  102. arr[*prear] = item;
  103. }
  104. int delFront(int *arr, int *pfront, int *prear)
  105. {
  106. int item;
  107. if (*pfront == -1)
  108. {
  109. printf("\nDeque is empty.\n");
  110. return 0;
  111. }
  112. item = arr[*pfront];
  113. arr[*pfront] = 0;
  114. if (*pfront == *prear)
  115. *pfront = *prear = -1;
  116. else
  117. (*pfront)++;
  118. return item;
  119. }
  120. int delRear(int *arr, int *pfront, int *prear)
  121. {
  122. int item;
  123. if (*pfront == -1)
  124. {
  125. printf("\nDeque is empty.\n");
  126. return 0;
  127. }
  128. item = arr[*prear];
  129. arr[*prear] = 0;
  130. (*prear)--;
  131. if (*prear == -1)
  132. *pfront = -1;
  133. return item;
  134. }
  135. void display(int *arr)
  136. {
  137. int i;
  138. printf("\n front: ");
  139. for (i = 0; i < MAX; i++)
  140. printf(" %d", arr[i]);
  141. printf(" :rear");
  142. }
  143. int count(int *arr)
  144. {
  145. int c = 0, i;
  146. for (i = 0; i < MAX; i++)
  147. {
  148. if (arr[i] != 0)
  149. c++;
  150. }
  151. return c;
  152. }
  1. // Deque operations in C++
  2. #include <iostream>
  3. using namespace std;
  4. #define MAX 10
  5. class Deque
  6. {
  7. int arr[MAX];
  8. int front;
  9. int rear;
  10. int size;
  11. public:
  12. Deque(int size)
  13. {
  14. front = -1;
  15. rear = 0;
  16. this->size = size;
  17. }
  18. void insertfront(int key);
  19. void insertrear(int key);
  20. void deletefront();
  21. void deleterear();
  22. bool isFull();
  23. bool isEmpty();
  24. int getFront();
  25. int getRear();
  26. };
  27. bool Deque::isFull()
  28. {
  29. return ((front == 0 && rear == size - 1) ||
  30. front == rear + 1);
  31. }
  32. bool Deque::isEmpty()
  33. {
  34. return (front == -1);
  35. }
  36. void Deque::insertfront(int key)
  37. {
  38. if (isFull())
  39. {
  40. cout << "Overflow\n"
  41. << endl;
  42. return;
  43. }
  44. if (front == -1)
  45. {
  46. front = 0;
  47. rear = 0;
  48. }
  49. else if (front == 0)
  50. front = size - 1;
  51. else
  52. front = front - 1;
  53. arr[front] = key;
  54. }
  55. void Deque ::insertrear(int key)
  56. {
  57. if (isFull())
  58. {
  59. cout << " Overflow\n " << endl;
  60. return;
  61. }
  62. if (front == -1)
  63. {
  64. front = 0;
  65. rear = 0;
  66. }
  67. else if (rear == size - 1)
  68. rear = 0;
  69. else
  70. rear = rear + 1;
  71. arr[rear] = key;
  72. }
  73. void Deque ::deletefront()
  74. {
  75. if (isEmpty())
  76. {
  77. cout << "Queue Underflow\n"
  78. << endl;
  79. return;
  80. }
  81. if (front == rear)
  82. {
  83. front = -1;
  84. rear = -1;
  85. }
  86. else if (front == size - 1)
  87. front = 0;
  88. else
  89. front = front + 1;
  90. }
  91. void Deque::deleterear()
  92. {
  93. if (isEmpty())
  94. {
  95. cout << " Underflow\n"
  96. << endl;
  97. return;
  98. }
  99. if (front == rear)
  100. {
  101. front = -1;
  102. rear = -1;
  103. }
  104. else if (rear == 0)
  105. rear = size - 1;
  106. else
  107. rear = rear - 1;
  108. }
  109. int Deque::getFront()
  110. {
  111. if (isEmpty())
  112. {
  113. cout << " Underflow\n"
  114. << endl;
  115. return -1;
  116. }
  117. return arr[front];
  118. }
  119. int Deque::getRear()
  120. {
  121. if (isEmpty() || rear < 0)
  122. {
  123. cout << " Underflow\n"
  124. << endl;
  125. return -1;
  126. }
  127. return arr[rear];
  128. }
  129. int main()
  130. {
  131. Deque dq(4);
  132. cout << "insert element at rear end \n";
  133. dq.insertrear(5);
  134. dq.insertrear(11);
  135. cout << "rear element: "
  136. << dq.getRear() << endl;
  137. dq.deleterear();
  138. cout << "after deletion of the rear element, the new rear element: " << dq.getRear() << endl;
  139. cout << "insert element at front end \n";
  140. dq.insertfront(8);
  141. cout << "front element: " << dq.getFront() << endl;
  142. dq.deletefront();
  143. cout << "after deletion of front element new front element: " << dq.getFront() << endl;
  144. }

双端队列复杂度

所有上述操作的时间复杂度是恒定的,即O(1)


双端队列应用

  1. 软件中的撤消操作。
  2. 在浏览器中存储历史记录。
  3. 为了实现队列