当前位置:   article > 正文

数据结构链式队列C++实现_c++链队列

c++链队列

1.链式队列

链式队列是基于单链表的存储表示。所以在实现链式队列时使用了和链表一样的结点struct,结点的具体定义放在"Queue.h"的头文件中。链式队列有两个指针front,rear,front为队头指针,指向单链表的第一个结点,rear为队尾指针,指向单链表的最后一个结点,所以出队是删除第一个节点,入队是将新元素的结点插在单链表最后一个结点的后面。结构图如下:

 本文链式队列对应的单链表没有设计空的头节点,因为头节点也没太大用处。

注意,当队列只有一个元素时,front == rear,因为该元素既是第一个元素也是最后一个元素。

2.队列基类的头文件"Queue.h"

这部分代码和上一篇循环队列的文章的Queue.h头文件相同,具体如下:

  1. #pragma once
  2. const int maxSize = 50; //顺序队列的最大元素个数
  3. template <class T>
  4. class Queue
  5. {
  6. public:
  7. Queue() {};
  8. ~Queue() {};
  9. virtual bool EnQueue(const T& x) = 0; //新元素入队
  10. virtual bool DeQueue(T& x) = 0; //队头元素出队
  11. virtual bool getFront(T& x) = 0; //获取队头元素
  12. virtual bool IsEmpty() const = 0; //判断队列是否为空
  13. virtual bool IsFull() const = 0; //判断队列是否满。顺序队列需要,链式队列不需要
  14. virtual int getSize() const = 0; //求队列元素的个数
  15. };
  16. //用struct定义节点,链式队才用的到
  17. template <class T>
  18. struct LinkNode {
  19. T data; //数据域
  20. LinkNode<T> * link; //指针域,指向下一个节点
  21. LinkNode() //仅初始化指针的构造函数
  22. {
  23. LinkNode<T> *ptr = nullptr;
  24. link = ptr;
  25. }
  26. LinkNode(const T& item, LinkNode<T> *ptr = nullptr) //初始化数据和指针成员的构造函数
  27. {
  28. data = item;
  29. link = ptr;
  30. }
  31. };

3.链式队列头文件“LinkedQueue.h”

该头文件定义和实现了链式队列的类模板及其相关接口的实现,代码如下:

  1. #include <iostream>
  2. #include "Queue.h"
  3. using namespace std;
  4. template <class T>
  5. class LinkedQueue :public Queue<T>
  6. {
  7. public:
  8. LinkedQueue() :front(nullptr), rear(nullptr) {} //构造函数
  9. ~LinkedQueue() { makeEmpty(); } //析构函数
  10. void makeEmpty(); //清空队列
  11. bool EnQueue(const T& x); //新元素x入队
  12. bool DeQueue(T& x); //队首元素出队并由x接收
  13. bool IsEmpty() const { return (front == nullptr) ? true : false; }//队列是否为空
  14. bool getFront(T& x); //查看队首元素的值并由x接收
  15. int getSize() const; //求队列元素的个数,这里的const修饰this指针,即该函数运行过程中不允许对队列进行更改
  16. //注意父类中纯虚函数IsFull(),该函数一定要重写,避免LinkedQueue称为虚类而无法实例化对象
  17. bool IsFull() const { return false; } //链式队列内存是动态的,所以没有“队满”的概念,因此该函数用不到,直接返回false
  18. //重载左移位运算符输出队列中的元素,同理为了避免模板声明发生混淆错误,这里用template <class R>来区分LinkedQueue类模板的template <class T>
  19. template <class R>
  20. friend ostream & operator<< (ostream &out, LinkedQueue<R> &lq); //全局函数做友元
  21. private:
  22. LinkNode<T> *front, *rear; //front指向对头节点的指针,rear指向队尾结点的指针
  23. };
  24. template <class T>
  25. void LinkedQueue<T>::makeEmpty()
  26. {
  27. LinkNode<T> *p;
  28. while (front != nullptr) //逐个删除队列中的结点
  29. {
  30. p = front; //记录front
  31. front = front->link; //front指向当前被删结点的下一个结点
  32. delete p; //释放当前节点的内存
  33. }
  34. }
  35. template <class T>
  36. bool LinkedQueue<T>::EnQueue(const T& x)
  37. {//入队的新元素放在队尾
  38. if (front == nullptr) //如果原队列为空
  39. {
  40. front = rear = new LinkNode<T>(x);//只有一个元素时,front和rear均指向该结点,因为该节点既是队头又是队尾
  41. if (front == nullptr)
  42. return false; //内存分配失败
  43. }
  44. else //如果原队列不为空
  45. {
  46. //先建立存放新元素的结点,并由队列最后一个节点的link指针指向该节点
  47. rear->link = new LinkNode<T>(x);
  48. //检测内存是否分配成功
  49. if (rear->link == nullptr)
  50. return false; //内存分配失败
  51. rear = rear->link; //更新rear使其指向队尾结点
  52. return true;
  53. }
  54. }
  55. template <class T>
  56. bool LinkedQueue<T>::DeQueue(T& x)
  57. {//如果队列不为空,将队首结点从链式队列中删除,函数返回true,否则返回false
  58. if (IsEmpty())
  59. return false;
  60. LinkNode<T> *p = front; //记录front指针
  61. x = front->data; //x接收元素数据
  62. front = front->link; //更新rear
  63. delete p; //清理队首结点的内存
  64. return true;
  65. }
  66. template <class T>
  67. bool LinkedQueue<T>::getFront(T& x)
  68. {//若队列不为空,返回队后元素的值及true,否则返回false
  69. if (IsEmpty())
  70. return false;
  71. x = front->data; //x接收队首元素的值
  72. return true;
  73. }
  74. template <class T>
  75. int LinkedQueue<T>::getSize() const
  76. {//求队列元素的个数
  77. LinkNode<T> *p = front; int num = 0;
  78. while (p != nullptr)
  79. {
  80. p = p->link; //遍历每一个结点
  81. num++; //元素个数加1
  82. }
  83. return num;
  84. }
  85. template <class R>
  86. ostream & operator<<(ostream &out, LinkedQueue<R> &lq)
  87. {
  88. out << "链式队列中元素的个数为:" << lq.getSize() << endl;
  89. LinkNode<R> *p = lq.front; int i = 0;
  90. while (p != nullptr)
  91. {
  92. out << i << " : " << p->data << endl;
  93. i++;
  94. p = p->link; //准备输出下一个元素
  95. }
  96. return out; //实现链式输出
  97. }

4.代码测试

老规矩,制作简单测试,剩下的小伙伴自行测试,放在“链式队列.cpp”文件中,代码如下:

  1. #include <iostream>
  2. #include "LinkedQueue.h"
  3. //LinkedQueue.h头文件已经有了using namespace std,所以这里就不用再写了
  4. int main()
  5. {
  6. LinkedQueue<int> LQ;
  7. for (int i = 0; i < 5; i++)
  8. LQ.EnQueue(i); //入队
  9. cout << LQ; //输出队列元素
  10. int x;
  11. LQ.DeQueue(x); //队首元素出队
  12. LQ.DeQueue(x);
  13. cout << LQ; //输出队列元素
  14. return 0;
  15. }

测试结果如下:

 

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

闽ICP备14008679号