当前位置:   article > 正文

C++ 队列(2)指针实现_c++ queue指针

c++ queue指针

本篇介绍通过链表和指针实现队列。

目录

一、逻辑结构:

二、概述:

三、相关操作:

1.复制构造函数:

2.析构函数:

3.=重载:

4.判空:

5.头节点数据:

6.入队:

7.出队:

8.打印队列数据:


一、逻辑结构

我们使用如下图所示的带尾指针的循环链表结构:

使用该结构是因为我们需要对头和尾进行操作,如果是带头指针的话尾部不好找到,而如果是带尾指针的循环链表,尾的next就是头,这样对两端的操作十分方便。

二、概述:

以下是要实现的功能:

  1. class Queue
  2. {
  3. private:
  4. class Node//存储数据的节点,由数据和指向下一个节点的指针组成
  5. {
  6. public:
  7. int data;
  8. Node* next;
  9. //构造函数
  10. Node(int newdata = 0, Node* nextptr = NULL) :data(newdata), next(nextptr) {};
  11. };
  12. Node* last;
  13. public:
  14. Queue() :last(NULL) {};//默认构造函数
  15. Queue(const Queue& origin);//复制构造函数
  16. ~Queue();//析构函数
  17. Queue& operator=(const Queue& origin);//=重载
  18. bool empty() const;//判空
  19. void enqueue(int newdata);//入队
  20. bool dequeue();//出队
  21. int front() const;//队头数据
  22. void display() const;//遍历队列
  23. };

三、相关操作:

1.复制构造函数

  1. Queue::Queue(const Queue& origin)
  2. {
  3. last = NULL;
  4. if (!origin.empty())
  5. {
  6. last = new Node(origin.last->data);//先给last开辟空间
  7. Node* orgptr = origin.last->next;//遍历origin的指针
  8. Node* curptr = last;//遍历当前队列的指针
  9. //遍历复制
  10. while (orgptr != origin.last)//遍历到最后一个就停止
  11. {
  12. curptr->next = new Node(orgptr->data);//每次开一个新节点
  13. orgptr = orgptr->next;
  14. curptr = curptr->next;
  15. }
  16. curptr->next = last;
  17. }
  18. }

代码中已经给出了注释,要注意的一点是我们的循环到origin.last就停止了,这时当前链表的倒数第二个节点的next还是null,所以在while循环之后还要把倒数第二个节点的next指向last。

2.析构函数

  1. Queue::~Queue()
  2. {
  3. if (!empty())
  4. {
  5. Node* ptr = last->next;//用于遍历的指针
  6. Node* nextptr = NULL;//存储next
  7. while (ptr != last)
  8. {
  9. nextptr = ptr->next;//把要删除节点的next先记下来,不然删完后就找不到了
  10. delete ptr;
  11. ptr = nextptr;
  12. }
  13. delete last;
  14. last = NULL;
  15. }
  16. }

遍历的指针ptr初始化为last->next,这是为了避免和while循环的条件冲突,如果直接令ptr=last,循环就开始不了了,因此在最后我们还要把没有被放到循环中的last删除。

3.=重载:

  1. Queue& Queue::operator=(const Queue& origin)
  2. {
  3. if (this != &origin)
  4. {
  5. this->~Queue();
  6. if (!origin.empty())
  7. {
  8. last = new Node(origin.last->data);
  9. Node* orgptr = origin.last->next;
  10. Node* curptr = last;
  11. while (orgptr != origin.last)
  12. {
  13. curptr->next = new Node(orgptr->data);
  14. orgptr = orgptr->next;
  15. curptr = curptr->next;
  16. }
  17. curptr->next = last;
  18. }
  19. }
  20. return *this;
  21. }

这个和复制构造函数基本一样,唯一的区别就是一开始的是不是本身的判断和析构函数的调用,如果不判断是不是本身而=右边又是自己的话,在第5行调用析构函数时本身就已经被删除了,无法进行复制,所以要判断一下。如果是本身就不用进行任何操作。

4.判空:

判空条件是尾为空。

  1. bool Queue::empty() const
  2. {
  3. return (last == NULL);
  4. }

5.头节点数据:

  1. int Queue::front() const
  2. {
  3. if (empty()) {
  4. cerr << "empty";
  5. exit(1);
  6. }
  7. else return last->next->data;
  8. }

6.入队:

在队尾加入新数据。

  1. void Queue::enqueue(int newdata)
  2. {
  3. if (empty())
  4. {
  5. last = new Node(newdata);
  6. last->next = last;
  7. }
  8. else
  9. {
  10. last->next = new Node(newdata, last->next);
  11. last = last->next;
  12. }
  13. }

这里要分队列为空和不为空两种情况,

1、为空时就为last开辟空间存放数据,此时只有一个数据,它既是头又是尾。

2、不为空就把新的节点放在last的next,而这个新节点的next就是原来的last->next,即头指针。

最后再令这个新节点为新的last。

7.出队:

删除头节点。

  1. bool Queue::dequeue()
  2. {
  3. if (empty()) return false;
  4. else if (last->next == last) {
  5. delete last;
  6. last = NULL;
  7. return true;
  8. }
  9. else {
  10. Node* newfirst = last->next->next;
  11. delete last->next;
  12. last->next = newfirst;
  13. return true;
  14. }
  15. }

三种情况:

1、队列为空直接返回false。

2、当队列只有一个数据时直接删除last。

3、当队列有多个元素时就需要调整指针,新的头节点为原来的第二个节点,因此last的next应在删除头节点后指向第二个节点。

8.打印队列数据:

  1. void Queue::display() const
  2. {
  3. if (!empty())
  4. {
  5. Node* ptr = last->next;
  6. while (ptr != last)
  7. {
  8. cout << ptr->data << " ";
  9. ptr = ptr->next;
  10. }
  11. cout << ptr->data << endl;
  12. }
  13. }

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

闽ICP备14008679号