双端队列(Deque)的应用、优点和缺点


双端队列(Deque)或双端队列是一种顺序线性集合数据队列,它提供类似于双端队列的功能。在这种数据结构中,方法不遵循先进先出(FIFO)规则来处理数据。这种数据结构也称为双端队列,因为元素被插入到队列的末尾,并从前端移除。对于双端队列,我们只能从两端添加和删除数据。双端队列操作的时间复杂度为 O(1)。双端队列有两种类型:

  • 输入受限

    • 仅在一端限制输入。

    • 允许从两端删除数据。

  • 输出受限

    • 仅在一端限制输出。

    • 允许从两端插入数据。

以下是一些命令,可以帮助程序员对双端队列上的数据集执行各种操作:

  • push_back() - 从双端队列的末尾插入一个元素。

  • push_front() - 从双端队列的开头插入一个元素。

  • pop_back() - 从双端队列的末尾移除元素。

  • pop_front() - 从双端队列的开头移除元素。

  • front() - 返回双端队列开头处的元素。

  • back() - 返回双端队列末尾处的元素。

  • at() - 设置/返回指定索引处的元素。

  • size() - 返回元素的数量。

  • empty() - 如果双端队列为空,则返回 true。

在循环数组中,我们可以使用双端队列操作。如果数组已满,则可以从开头开始该过程。但是对于线性数组,如果数组已满,则无法再插入数据。然后我们会看到一个“溢出弹出窗口”。

双端队列的应用

双端队列有许多实际应用。

  • 用于作业调度应用程序。

  • 我们可以在 O(1) 时间内执行顺时针和逆时针旋转操作。

  • 双端队列算法也存在于网页浏览器历史记录中。

  • 用于排序中的撤销操作。

双端队列的优点

双端队列有很多优点。

  • 我们可以从前端和后端添加和删除数据。

  • 它们的大小是动态的。

  • 双端队列提供了执行操作的高效时间。

  • 这里使用 LIFO 栈。

  • 此处无法进行重新分配。

  • 它是一个通过适当同步实现的线程安全过程。

  • 缓存友好。

双端队列的缺点

双端队列的缺点是

  • 双端队列过程具有更高的内存消耗率。

  • 它在多线程中存在同步问题。

  • 无法在所有平台上实现。

  • 不适合实现排序操作。

  • 双端队列的功能数量较少。

双端队列操作的算法

  • 步骤 1 - 考虑一个大小为 n 的双端队列数组。

  • 步骤 2 - 设置两个指针,"front=-1" 用于前端,"rear=0" 用于设置。

此过程中有很多子部分。在双端队列中,我们可以执行多个操作。我们在这里对它们进行了总结。

  • 在双端队列中从前端插入数据的算法:

    • 步骤 1 - 检查前端位置。

    • 步骤 2 - 如果 "front<1",则将 "front=n-1" 应用于最后一个索引。

    • 步骤 3 - 否则,我们需要将 "front" 减 1。

    • 步骤 4 - 将一个新的键元素添加到数组的前端位置。

  • 在双端队列中在后端插入数据的算法:

    • 步骤 1 - 检查数组是否已满。

    • 步骤 2 - 如果已满,则应用 "rear=0"。

    • 步骤 3 - 否则,将 "rear" 的值增加 1。

    • 步骤 4 - 再次将一个新的键添加到 "array[rear]" 中。

  • 从双端队列的前端删除数据的算法:

    • 步骤 1 - 检查双端队列是否为空。

    • 步骤 2 - 如果列表为空 ("front=-1"),则为下溢条件,无法执行删除操作。

    • 步骤 3 - 如果双端队列中只有一个元素,则 "front=rear=-1"。

    • 步骤 4 - 否则,"front" 在末尾,则设置为转到 "front=0"。

    • 步骤 5 - 否则,front=front+1。

  • 从双端队列的后端删除数据的算法:

    • 步骤 1 - 检查双端队列是否为空。

    • 步骤 2 - 如果为空 ("front=-1"),则无法执行删除操作。这是一个下溢条件。

    • 步骤 3 - 如果双端队列中只有一个数据,则 "front=rear=-1"。

    • 步骤 4 - 否则,请执行以下操作。

    • 步骤 5 - 如果 rear 在前端 "rear=0"。转到前端 "rear = n-1"。

    • 步骤 6 - 否则,rear=rear-1。

  • 检查双端队列是否为空的算法:

    • 步骤 1 - 如果 front=-1,则双端队列为空。

  • 检查双端队列是否已满的算法:

    • 步骤 1 - 如果 front=0 且 rear = n-1

    • 步骤 2 - 或 front=rear+1

双端队列的语法

deque< object_type > deque_name;
deque<int> deque1 = {11, 21, 31, 41, 51};
deque<int> deque2 {10, 20, 30, 40, 50};

在数据结构中,双端队列继承了栈和队列的一些属性。在 C++ 中,双端队列实现为向量(vector)的向量。

使用双端队列的各种方法

  • 方法 1 - 以一般方式实现双端队列

  • 方法 2 - 将元素插入双端队列

  • 方法 3 - 从双端队列访问元素

  • 方法 4 - 更改双端队列的元素

以一般方式实现双端队列

在此 C++ 构建代码中,我们以一般方式配置了双端队列操作。在此示例中,我们在队列的后端插入了一个元素,并且整个系统已按照该方式执行。

示例 1

#include <iostream>
using namespace std;
#define MAX 10

class Deque {
   int arr[MAX];
   int front;
   int rear;
   int size;

   public:
   Deque(int size) {
      front = -1;
      rear = 0;
      this->size = size;
   }

   void insertfront(int key);
   void insertrear(int key);
   void deletefront();
   void deleterear();
   bool isFull();
   bool isEmpty();
   int getFront();
   int getRear();
};
bool Deque::isFull() {
   return ((front == 0 && rear == size - 1) ||
      front == rear + 1);
}
bool Deque::isEmpty() {
   return (front == -1);
}
void Deque::insertfront(int key) {
   if (isFull()) {
      cout << "Overflow\n"
         << endl;
      return;
  }
  if (front == -1) {
     front = 0;
     rear = 0;
  }
  else if (front == 0)
     front = size - 1;
   else
     front = front - 1;
   arr[front] = key;
}
void Deque ::insertrear(int key) {
  if (isFull()) {
    cout << " Overflow\n " << endl;
    return;
  }

  if (front == -1) {
    front = 0;
    rear = 0;
  }

  else if (rear == size - 1)
    rear = 0;

  else
    rear = rear + 1;

  arr[rear] = key;
}
void Deque ::deletefront() {
   if (isEmpty()) {
      cout << "Queue Underflow\n"
      << endl;
      return;
   }

   if (front == rear) {
      front = -1;
      rear = -1;
   } else if (front == size - 1)
      front = 0;
   else
      front = front + 1;
}
void Deque::deleterear() {
   if (isEmpty()) {
      cout << " Underflow\n"
      << endl;
    return;
   }

   if (front == rear) {
       front = -1;
      rear = -1;
   } else if (rear == 0)
      rear = size - 1;
   else
      rear = rear - 1;
}
int Deque::getFront() {
   if (isEmpty()) {
      cout << " Underflow\n"
      << endl;
      return -1;
   }
   return arr[front];
}
int Deque::getRear() {
   if (isEmpty() || rear < 0) {
      cout << " Underflow\n"
      << endl;
      return -1;
   }
   return arr[rear];
}
int main() {
   Deque dq(4);
   cout << "insert element at rear end \n";
   dq.insertrear(5);
   dq.insertrear(11);
   cout << "rear element: "
   << dq.getRear() << endl;
   dq.deleterear();
   cout << "after deletion of the rear element, the new rear element: " << dq.getRear() << endl;
   cout << "insert element at front end \n";
   dq.insertfront(8);
   cout << "front element: " << dq.getFront() << endl;
   dq.deletefront();
   cout << "after deletion of front element new front element: " << dq.getFront() << endl;
}

输出

insert element at rear end 
rear element: 11
after deletion of the rear element, the new rear element: 5
insert element at front end 
front element: 8
after deletion of front element new front element: 5

将元素插入双端队列

在此代码中,我们尝试创建 C++ 代码以将元素插入双端队列。有两种方法可以执行此操作。

  • push_back() - 将元素插入数组的末尾。

  • push_front() - 将元素插入数组的开头。

示例 2

#include <iostream>
#include <deque>
using namespace std;
int main() {
   deque<int> nums {16, 7};
   cout << "Initial Deque As We Give: ";
   for (const int& num : nums) {
      cout << num << ", ";
   }
   nums.push_back(2001);
   nums.push_front(1997);
   cout << "\nFinal Deque Is Here: ";
   for (const int& num : nums) {
      cout << num << ", ";
   }
   return 0;
}

输出

Initial Deque As We Give: 16, 7, 
Final Deque Is Here: 1997, 16, 7, 2001,

从双端队列访问元素

我们可以使用两种方法从双端队列访问元素。

  • front() - 可以在前端获取返回值。

  • back() - 从后端返回数据。

  • at() - 从指定索引返回数据。

#include <iostream>
#include <deque>
using namespace std;
int main() {
   deque<int> nums {16, 07, 10};
   cout << "Front element are here: " << nums.front() << endl;
   cout << "Back element are here: " << nums.back() << endl;
   cout << "Element at index 1 present here: " << nums.at(1) << endl;
   cout << "Element at index 0 present here: " << nums[0];
   return 0;
}

输出

Front element are here: 16
Back element are here: 10
Element at index 1 present here: 7
Element at index 0 present here: 16

更改双端队列的元素

在此代码中,我们可以使用 at() 方法替换或更改该特定双端队列的元素。

示例 4

#include <iostream>
#include <deque>
using namespace std;
int main() {
   deque<int> nums = {07,16,10,1997,2001};
   cout << "Initial Deque: ";
   for (const int& num : nums) {
      cout << num << ", ";
   }
   nums.at(0) = 2022;
   nums.at(1) = 10-05;
   cout << "\nUpdated Deque: ";
   for (const int& num : nums) {
      cout << num << ", ";
   }
   return 0;
}

输出

Initial Deque: 7, 16, 10, 1997, 2001, 
Updated Deque: 2022, 5, 10, 1997, 2001,

结论

通过本文,我们学习了双端队列、其操作方法、应用、优点和缺点,以及使用 C++ 的算法和可能的代码。

更新于:2023年4月6日

2K+ 浏览量

开启你的 职业生涯

通过完成课程获得认证

开始学习
广告