数据结构之队列queue
来源:互联网 发布:竞彩代购软件 编辑:程序博客网 时间:2024/05/21 17:08
C++数据结构之队列queue
什么是队列
队列的基本特征
队列是如何工作的
队列的实现
队列的应用
什么是队列
与栈相反,队列是一种先进先出(FIFO)的线性表,只允许在表的一端插入,在另一端删除。允许插入的一端叫队尾,允许删除 的一端叫队头。比较典型的例子有日常生活中的排队:银行排序办理业务、地铁排队上车(emmmm,这里假设所有人都遵守秩序)等,当然还有计算机系统的消息队列,操作系统的作业调度(这两者都可以看做是队列,不过是队列的高级应用:优先级队列)等
队列的基本特征
- 先进先出(FIFO)- 限制插入和删除:队尾(back)插入,队头(front)删除
队列是如何工作的
如下图所示:
front代表队头,back代表队尾,初始状态,front与back指向同一位置,当插入一个新元素a后,队尾back向后移动一位,队头front不动,指向下一个位置,当在a的下一个位置插入元素b时,队尾back继续向后移动一位,直到满队列,此时back指向最后的位置。当删除一个元素时,队头front向后移动一位,队尾back不动。在这种队列结构下,可以通过(front == back)来判断队列是否为空。
队列的实现
队列的实现主要有两种方式:顺序表和链表;队列的操作主要有:取出队头元素(front())、删除队头元素(pop())、队尾插入元素(push())、是否为空(Empty())、队列元素数(size())、是否已满(Full())
顺序表实现队列
顺序表的实现较为简单,直接使用数据存储数据即可,而front和back代表数组的下标(索引),这样做的缺点就是队列的长度固定,同时由于每次删除元素时,队头向后移动一位,当队列中所有元素被删除时,此时front ==back,但是,此时继续向队列中插入元素时,就会出现数组越界的情况。
如上所示,此时,front与back都以指向了最后位置,无法继续在队列中插入数,但是,front前面的空间仍旧是空的,没有存储内容,此时如果采用动态内存分配无疑会浪费内存空间,因此,为了能够充分利用已分配的数组空间,可以将数组想象为一个首尾相接的环,循环存储数据,称之为循环队列。
如上,将数组想象成环状,初始时,front与back都指向起始位置,当有元素插入或者删除时,进行相应的移动,直到back的下一个位置为front时,队列为满。由于是环状的,因此,front与back的代表的位置应该对队列的长度取余后,才为数组的下标。同时,为了便于判断队列为满和队列为空,在设置队列长度时,应该为length+1,因为back始终指向队尾元素的下一个位置,所以,当队列满时,back应该指向队列长度的下一个位置,从而,可以通过(back+1)%(length+1) == front判断队列满,通过back==front判断队列为空。
代码实现
//头文件定义template <typename T>class Queue {public: Queue(int max_size); virtual ~Queue(); T & Front() const; void Pop(); void Push(T &element); bool Empty() const; int size() const; bool Full() const;private: int front_; int back_; int size_; int max_size_; T *contain; //队列指针};//代码实现#include "Queue.h"#include <iostream>#include <assert.h> //////////////////////////////////////////////////////////////////////// Construction/Destruction//////////////////////////////////////////////////////////////////////template <typename T>Queue<T>::Queue(int max_size) { front_ = back_ = 0; size_ = 0; max_size_ = max_size + 1; contain = new T[max_size_]; //比队列长度多一个元素,用于辅助存放back_以及判断满}template <typename T>Queue<T>::~Queue() { delete [] contain;}template <typename T>bool Queue<T>::Empty() const { return front_ == back_; //指向同一位置}template <typename T>T & Queue<T>::Front() const { assert(!Empty()); //断言不为空,为空则程序直接报出异常中止 return contain[front_];}template <typename T>bool Queue<T>::Full() const { return (back_ + 1) % max_size_ == front_; //由于是环状所以对最大长度取余}template <typename T>void Queue<T>::Pop() { front_ = (front_ + 1) % max_size_; size_--;}template <typename T>void Queue<T>::Push(T &element) { assert(!Full()); contain[back_] = element; back_ = (back_ + 1) % max_size_; size_++;}template <typename T>int Queue<T>::size() const { return size_;}
链表实现队列
用链表来实现队列更符合队列的特征,不需要进行循环,删除队头元素直接释放队头元素空间即可,插入队尾时,直接新增空间即可添加,同时队尾指针指向队尾元素,不再指向下一节点,如下图所示。
与链表不同的是,链表有头结点,而队列不需要头结点,空队列时,队头指针与队尾指针都指向NULL,同时此时判断队列满也没有什么意义。因而用链表实现队列的功能有取头节点(Front())、删除头节点(Pop())、插入新元素(Push())、是否为空(Empty())、队列中元素个数(size())
代码实现
//头文件定义template <typename T>//节点struct ListNode{ T data; ListNode<T> *link;};//链表类template <typename T>class ListQueue {public: ListQueue(); virtual ~ListQueue(); T & front() const; void Pop(); void Push(T &element); bool Empty() const; int size() const;private: int size_; ListNode<T> *front_; ListNode<T> *back_;};//cpp实现#include "ListQueue.h"#include <iostream>#include <assert.h>//////////////////////////////////////////////////////////////////////// Construction/Destruction//////////////////////////////////////////////////////////////////////template <typename T>ListQueue<T>::ListQueue() { front_ = back_ = NULL; size_ = 0;}template <typename T>ListQueue<T>::~ListQueue() { while (!Empty()) { this->Pop(); }}template <typename T>bool ListQueue<T>::Empty() const { return front_ == NULL;}template <typename T>T & ListQueue<T>::front() const{ assert(!Empty()); return front_->data;}template <typename T>void ListQueue<T>::Pop() { assert(!Empty()); ListNode<T> *temp = front_; front_ = front_->link; delete temp; size_--;}template <typename T>void ListQueue<T>::Push(T &element) { ListNode<T> *new_node= new ListNode<T>; new_node->data = element; new_node->link = NULL; if (back_ == NULL) { front_ = back_ = new_node; } else { back_->link = new_node; back_ = back_->link; } size_++;}template <typename T>int ListQueue<T>::size() const { return size_;}
队列的应用
编程练习之队列篇:舞伴问题
编程练习之队列篇:游程编码问题
编程练习之队列篇:杨辉三角问题
编程练习之队列篇:优先级队列
未完待续
以上是我关于队列的学习心得,如果有什么不对的地方,欢迎大家指出,一起交流讨论
阅读全文
0 0
- 数据结构之队列queue
- Java 数据结构之 Queue(队列)
- C++数据结构之Queue(队列)
- C++数据结构 之 优先队列_Priority Queue
- Java数据结构与算法之Queue队列
- 数据结构学习之队列(queue)
- [Java数据结构]线性表之队列Queue
- 数据结构队列之环形队列的动态数组实现:queue
- 队列数据结构 Queue.h
- 【数据结构】顺序队列 Queue
- 数据结构-队列(queue)
- 数据结构_队列(queue)
- 数据结构-队列(queue)
- 数据结构复习 - 队列Queue
- 队列(queue)数据结构
- 数据结构-队列(Queue)
- [C++数据结构]队列Queue
- C#数据结构--队列Queue
- 最新 android studio 基本环境配置
- MVP模式OKhttp请求RecyclerView展示数据
- 数据分配和复制
- Java字符串处理的几个常用方法
- Linux:网络编程
- 数据结构之队列queue
- 编写多线程程序,模拟多个人通过一个山洞。
- Javascript学习笔记(console对象)
- python 学习笔记 9 -- Python强大的自省简析
- Leetcode:714. Best Time to Buy and Sell Stock with Transaction Fee
- dubbo--1.系统架构
- Spring核心理解
- 中北大学NUC2017新生赛1004/NOJ-1984
- ExtJs xtype的使用