当前位置:   article > 正文

数据结构整理-队列(双向)篇_双向队列函数

双向队列函数

单向队列仅能从队列的头部删除元素、在队列的尾部添加元素。与其相比,双向队列的灵活性更好,可以在头尾执行元素的添加或删除。

一般编程语言中有已实现的双向队列,双向队列的一般操作有:

注意:上面的方法名不一定是双向队列的正确的成员函数名,只是便于理解。

使用编程语言内部的双向队列有以下代码:

  1. //初始化双向队列
  2. deque<int> deque;
  3. //入队
  4. deque.push_back(2);//队尾加入元素
  5. deque.push_back(3);
  6. deque.push_front(7);//队首加入元素
  7. deque.push_front(8);
  8. //此时双向队列:8 7 2 3
  9. //访问双向队列的元素
  10. int front =deque.front();//队首元素
  11. int back = deque.back();//队尾元素
  12. //元素出队
  13. deque.pop_front();//队首元素出队,此时双向队列:7 2 3
  14. deque.pop_back();//队尾元素出队,此时双向队列: 7 2
  15. //获取双向队列的长度
  16. int size=deque.size();
  17. //判断双向队列是否为空
  18. bool empty = deque.empty();

双向队列的实现与队列比较类似,同样可以使用数组或者链表实现底层数据结构。

1.基于数组的实现

  1. class ArrayDeque{
  2. private:
  3. vector<int> nums;//储存双向队列的数组
  4. int front;//队首指针,指向队首元素
  5. int queSize;//双向队列的长度
  6. public:
  7. //构造函数,初始化双向队列
  8. ArrayDeque(int capacity){
  9. nums.resize(capacity);//由于本数组使用的内置动态数组,直接使用成员函数初始化数组容量
  10. front = queSize=0;
  11. }
  12. //析构函数不再需要,因为内置动态数组一般内存会自动释放,手动开辟的数组空间需要手动释放
  13. //获取双向队列的容量(容量是最大可以存多少个元素)
  14. int capacity(){
  15. return nums.size();
  16. }
  17. //获取双向队列的长度(长度是目前存了多少元素)
  18. int size(){
  19. return queSize;
  20. }
  21. //判断双向队列是否为空
  22. bool isEmpty(){
  23. return queSize==0;
  24. }
  25. //计算环形数组的索引
  26. int index(int i){
  27. //通过取余操作实现数组首尾相连
  28. //当i越过数组尾部后,回到头部
  29. //当i越过数组头部后,回到尾部
  30. return (i+capacity())%capacity();
  31. }
  32. //队首入队
  33. void pushFirst(int num){
  34. if(queSize==capacity()){
  35. cout<<"双向队列已满"<<endl;
  36. return;
  37. }
  38. //队首指针向左移动一位
  39. //通过取余操作实现front越过数组头部回到数组尾部
  40. front = index(front - 1);
  41. //将num添加至队首
  42. nums[front]=num;
  43. queSize++;
  44. }
  45. //队尾入队
  46. void pushLast(int num){
  47. if(queSize==capacity()){
  48. cout<<"双向队列已满"<<endl;
  49. return;
  50. }
  51. //队尾指针向右移动一位
  52. int rear = index(front+queSize);
  53. //将num添加至队尾
  54. nums[rear]=num;
  55. queSize++;
  56. }
  57. //获取队首元素
  58. int peekFirst(){
  59. if(isEmpty()) throw out_of_range("双向队列是空");
  60. return nums[front];
  61. }
  62. //获取队尾元素
  63. int peekLast(){
  64. if(isEmpty()) throw out_of_range("双向队列是空");
  65. //计算队尾元素索引
  66. int last =index(front+queSize-1);
  67. return nums[last];
  68. }
  69. //队首出队
  70. int popFirst(){
  71. int num=peekFirst();
  72. //队首元素向右移动一位
  73. front=index(front+1);
  74. queSize--;
  75. return num;
  76. }
  77. //队尾出队
  78. int popLast(){
  79. int num=peekLast();
  80. queSize--;
  81. return num;
  82. }
  83. //返回数组用于打印
  84. vector<int> toVector(){
  85. //仅转换有效长度范围内的队列元素
  86. vector<int> res(queSize);
  87. for(int i =0, j=front;i<queSize;i++,j++){
  88. res[i]=nums[index(j)];
  89. }
  90. return res;
  91. }
  92. };

2.基于双向链表实现

  1. struct DoublyListNode{
  2. int val;
  3. DoublyListNode* next;
  4. DoublyListNode* prev;
  5. DoublyListNode(int val): val(val),prev(nullptr),next(nullptr){}
  6. };
  7. //基于双向链表实现的双向队列
  8. class LinkedListDeque{
  9. private:
  10. DoublyListNode *front, *rear;//头节点front,尾节点rear
  11. int queSize=0;
  12. public:
  13. //构造函数
  14. LinkedListDeque(): front(nullptr),rear(nullptr){}
  15. //析构函数
  16. ~LinkedListDeque(){
  17. //遍历链表,删除节点,释放内存
  18. DoublyListNode* pre, *cur=front;
  19. while(cur!=nullptr){
  20. pre=cur;
  21. cur=cur->next;
  22. delete pre;
  23. }
  24. }
  25. //获取双向队列的长度
  26. int size(){
  27. return queSize;
  28. }
  29. //判断双向队列是否为空
  30. bool isEmpty(){
  31. return size()==0;
  32. }
  33. //入队操作
  34. void push(int num, bool isFront){
  35. DoublyListNode *node=new DoublyListNode(num);
  36. //若链表为空,则令front和rear都指向node
  37. if(isEmpty()) front = rear = node;
  38. //队首入队操作
  39. else if (isFront){
  40. //将node添加至链表头部
  41. front->prev=node;
  42. node->next=front;
  43. front=node;//更新头节点
  44. }else{
  45. //队尾入队操作
  46. //将node添加至链表尾部
  47. rear->next=node;
  48. node->prev=rear;
  49. rear=node;//更新尾节点
  50. }
  51. queSize++;//更新队列长度
  52. }
  53. //队首入队
  54. void pushFirst(int num){
  55. push(num,true);
  56. }
  57. //队尾入队
  58. void pushLast(int num){
  59. push(num,false);
  60. }
  61. //出队操作
  62. int pop(bool isFront){
  63. if(isFront) throw out_of_range("队列为空");
  64. int val;
  65. //队首出队操作
  66. if(isFront){
  67. val=front->val;//暂存头节点值
  68. //删除头节点
  69. DoublyListNode* fNext = front->next;
  70. if(fNext!=nullptr){
  71. fNext->prev=nullptr;
  72. front->next=nullptr;
  73. }
  74. delete front;
  75. front=fNext;//更新头节点;
  76. }else{
  77. //队尾出队操作
  78. val=rear->val;//暂存尾节点值
  79. //删除尾节点
  80. DoublyListNode *rPrev=rear->prev;
  81. if(rPrev!=nullptr){
  82. rPrev->next=nullptr;
  83. rear->prev=nullptr;
  84. }
  85. delete rear;
  86. rear=rPrev;//更新尾节点
  87. }
  88. queSize--;//更新队列长度
  89. return val;
  90. }
  91. //队首出队
  92. int popFirst(){
  93. return pop(true);
  94. }
  95. //队尾出队
  96. int popLast(){
  97. return pop(false);
  98. }
  99. //访问队首元素
  100. int peekFirst(){
  101. if(isEmpty()) throw out_of_range( " 双向队列为空");
  102. return front->val;
  103. }
  104. //访问队尾元素
  105. int peekLast(){
  106. if(isEmpty()) throw out_of_range( " 双向队列为空");
  107. return rear->val;
  108. }
  109. //返回数组用于打印
  110. vector<int> toVector(){
  111. DoublyListNode* node=front;
  112. vector<int> res(size());
  113. for(int i=0;i<res.size();i++){
  114. res[i]=node->val;
  115. node=node->next;
  116. }
  117. return res;
  118. }
  119. };

声明:本人所写内容全部参考hello-algo,仅用于个人复习。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/人工智能uu/article/detail/891733
推荐阅读
相关标签
  

闽ICP备14008679号