C++数据结构——队列

参考博客:

  • 数据结构图文解析之:队列详解与C++模板实现
  • C++ stl队列Queue用法介绍:删除,插入等操作代码举例

1、队列(Queue)与栈一样,是一种线性存储结构,它具有如下特点:

(1)队列中的数据元素遵循“先进先出”(First In First Out)的原则,简称FIFO结构;

(2)在队尾添加元素,在队头删除元素。

2、队列的相关概念:

(1)队头与队尾: 允许元素插入的一端称为队尾,允许元素删除的一端称为队头;

(2)入队:队列的插入操作;

(3)出队:队列的删除操作。

3、队列的操作:

(1)入队: 通常命名为push()

(2)出队: 通常命名为pop()

(3)求队列中元素个数

(4)判断队列是否为空

(5)获取队首元素

4、队列的分类:

(1)基于数组的循环队列(循环队列)

(2)基于链表的队列(链队列)

5、实例分析

C++队列queue模板类的定义在<queue>头文件中,queue 模板类需要两个模板参数,一个是元素类型,一个容器类型,元素类型是必要的,容器类型是可选的,默认为deque 类型。C++队列Queue是一种容器适配器,它给予程序员一种先进先出(FIFO)的数据结构。

那么我们如何判断队列是空队列还是已满呢?

a、栈空: 队首标志=队尾标志时,表示栈空。

b、栈满 : 队尾+1 = 队首时,表示栈满。

使用标准库的队列时, 应包含相关头文件,在栈中应包含头文件: #include< queue> 。定义:queue< int > q;

q.empty()               如果队列为空返回true,否则返回false
q.size()                返回队列中元素的个数
q.pop()                 删除队列首元素但不返回其值
q.front()               返回队首元素的值,但不删除该元素
q.push()                在队尾压入新元素
q.back()                返回队列尾元素的值,但不删除该元素

(1)基于数组的循环队列(循环队列)

以数组作为底层数据结构时,一般讲队列实现为循环队列。这是因为队列在顺序存储上的不足:每次从数组头部删除元素(出队)后,需要将头部以后的所有元素往前移动一个位置,这是一个时间复杂度为O(n)的操作。具体的示例图参考:http://www.cnblogs.com/QG-whz/p/5171123.html。

循环队列,可以把数组看出一个首尾相连的圆环,删除元素时将队首标志往后移动,添加元素时若数组尾部已经没有空间,则考虑数组头部的空间是否空闲,如果是,则在数组头部进行插入。参考博客:【c++版数据结构】之循环队列的实现,判断循环队列是“空”还是“ 满”,有两种处理方法:

  • A. 设置状态标志位以区别空还是满
  • B. 少用一个元素,约定“队头front在队尾rear的下一个位置(指的是环的下一个位置)”作为“满”的标志

        C语言中,不能用动态分配的一维数组来实现循环队列,如果用户的应用程序中设有循环队列,则必须为它设定一个最大队列长度;如果用户无法预估所用队列的最大长度,则宜采用链队列。

定义front为队列头元素的位置,rear为队列尾元素的位置,MAXSIZE为循环队列的最大长度。注意以下几点,循环队列迎刃而解:

  • A.  求元素的个数:(rear - front + MAXSIZE) % MAXSIZE
  • B.  front/rear指向逻辑的下一个空间  front =(front+1)%MAXSIZE,rear = (rear+1)%MAXSIZE
  • C.  判空:front == rear
  • D.  判满:(rear+1+MAXSZIE) == front

例子1、简单的队列操作

#include <queue>
#include <iostream>
using namespace std;int main(){queue<int> q;for (int i = 0; i < 10; i++){q.push(i);}if (!q.empty()){cout << "队列q非空!" << endl;cout << "q中有" << q.size() << "个元素" << endl;}cout << "队头元素为:" << q.front() << endl;cout << "队尾元素为:" << q.back() << endl;for (int j = 0; j < 10; j++){int tmp = q.front();cout << tmp << " ";q.pop();}cout << endl;if (!q.empty()){cout << "队列非空!" << endl;}system("pause");return 0;
}
运行结果:
例子2、循环队列的C++实现
#include <iostream>
#include <queue>
#include <string>
using namespace std;template <typename T>
class LoopQueue
{
public:LoopQueue(int c = 10);~LoopQueue();bool isEmpty();        //队列的判空int size();            //队列的大小bool push(T t);        //入队列bool pop();            //出队列T front();            //队首元素private:int capacity;int begin;int end;T*  queue;
};template<typename T>
LoopQueue<T>::LoopQueue(int c = 10):capacity(c), begin(0), end(0), queue(nullptr)
{queue = new T[capacity];
};template<typename T>
LoopQueue<T>::~LoopQueue()
{delete[]queue;
}template <typename T>
bool LoopQueue<T>::isEmpty()                   //判断循环队列是否为空
{if (begin == end)return true;return false;
};template<typename T>
int LoopQueue<T>::size()
{return (end - begin + capacity) % capacity; //计算循环队列的长度
};template<typename T>
bool LoopQueue<T>::push(T t)
{if (end + 1 % capacity == begin)            //判断队列是否已满{return false;}queue[end] = t;end = (end + 1) % capacity;return true;
};template <typename T>
bool LoopQueue<T>::pop()                        //判断队列是否为空
{if (end == begin) {return false;}begin = (begin + 1) % capacity;return true;
};template <typename T>
T LoopQueue<T>::front()
{if (end == begin){return false;}return queue[begin];
};int main()
{LoopQueue<string> queue(6);queue.push("one");queue.push("two");queue.push("three");queue.push("four");queue.push("five");cout << "队列长度" << queue.size() << endl;while (!queue.isEmpty()){cout << queue.front() << endl;queue.pop();}getchar();//system("pause");return 0;
}

运行结果:

(2)基于链表的队列(链队列)

链队列是基于链表实现的队列,它不存在数组的O(n)的元素移动问题或空间浪费问题。我们所要确定的就是链表哪头做队首,哪头做队尾。显然我们应该以链表头部为队首,链表尾部为队尾。存储一个指向队尾的指针,方便从链表尾插入元素;使用带头节点的链表,方便从链表头删除元素。

代码参考:链式队列的C++实现

#include <iostream>
#include <cstdlib>
using namespace std;struct QNode    //定义队列结点的数据结构
{QNode *next; //指针域,指向下一个结点double data;    //数据域,存储队列信息
};struct LinkQueue    //定义队列的数据结构
{QNode *front;      //队首指针,指向QNode类型的指针QNode *rear;       //队尾指针
};void InitQueue(LinkQueue &Q)     //构造一个空的队列
{QNode *q;q = new QNode;    //申请一个结点的空间q->next = NULL;   //当作头结点//队首与队尾指针都指向这个结点,指针域为NULLQ.front = q;Q.rear = q;
}int IsEmpty(LinkQueue &Q)    //判断队列是否为空
{if (Q.rear == Q.front)return 0;elsereturn 1;
}void EnQueue(LinkQueue &Q, double e)     //从队列尾部插入元素
{QNode *p;    //新创建一个结点p = new QNode;p->next = NULL;p->data = e;  //输入数据信息//将新结点插入队列尾部Q.rear->next = p;Q.rear = p;       //设置新的尾结点
}void DeQueue(LinkQueue &Q, double &e)   //从队列首部删除一个结点
{QNode *p;p = Q.front->next;e = p->data;    //保存要出队列的数据Q.front->next = p->next;       //将下一个结点当作头结点后面链接的第一个结点if (Q.rear == p)    //如果要删除的元素即为尾结点,则将头指针赋予尾指针,一同指向头结点,表示队列为空Q.rear = Q.front;delete p;
}void DestoryQueue(LinkQueue &Q)       //销毁一个队列
{while (Q.front){Q.rear = Q.front;    //从头节点开始,一个一个删除队列结点,释放空间delete Q.front;Q.front = Q.rear;}
}
int main()
{LinkQueue *Q;  //定义一个队列QQ = new LinkQueue;InitQueue(*Q);cout << "开始往队列里输入数据,以-1作为结束符" << endl;cout << "请输入一个数:" << endl;double a, x;cin >> a;while (a != -1){EnQueue(*Q, a);cout << "请输入一个数:" << endl;cin >> a;}//输出队列元素,队首->队尾QNode *p;p = Q->front->next;if (p == NULL)     //如果为空表,直接退出{cout << "队列为空!" << endl;return 0;}cout << "队列数据依次为:" << endl;while (p != NULL){cout << p->data << " ";p = p->next;}cout << endl;//删除队列元素while (!IsEmpty(*Q)){DeQueue(*Q, x);cout << x << " ";}//释放内存空间delete Q->front;delete Q;system("pause");return 0;
}

运行结果:

还可以参考代码:C++ 链队列和循环队列基本操作。

总结:

1、循环队列中判断队空的方法是判断front==rear,队满的方法是判断front=(rear+1)%MAXSIZE。(为什么不用一个length表示队长,当length==maxSize时表示队满,原因就是,在频繁的队列操作中,多出一个变量会大量的增加执行时间,所以不如浪费一个数组空间来得划算。)

2、用单链表表示的链式队列特别适合于数据元素变动较大的情形,而且不存在溢出的情况。

C++数据结构——队列相关推荐

  1. java 数据结构_Java版-数据结构-队列(数组队列)

    前言 看过笔者前两篇介绍的 Java版数据结构 数组和 栈的盆友,都给予了笔者一致的好评,在这里笔者感谢大家的认可!!! 由于本章介绍的数据结构是 队列,在队列的实现上会基于前面写的 动态数组来实现, ...

  2. 数据结构——队列的C++实现

    数据结构--队列的C++实现 \qquad队列的创建.判断是否为空或者满.入队和出队操作的C++实现. #include<iostream> using namespace std;//1 ...

  3. java 数据队列_Java 数据结构 - 队列

    Java 数据结构 - 队列 我们今天要讲的数据结构是队列,比如 Java 线程池任务就是队列实现的. 1. 什么是队列 和栈一样,队列也是一种操作受限的线性结构.使用队列时,在一端插入元素,而在另一 ...

  4. 数据结构队列代码_代码简介:队列数据结构如何工作

    数据结构队列代码 Here are three stories we published this week that are worth your time: 这是我们本周发布的三个值得您关注的故事 ...

  5. java循环队列_Java版-数据结构-队列(循环队列)

    前情回顾 在上一篇,笔者给大家介绍了数组队列,并且在文末提出了数组队列实现上的劣势,以及带来的性能问题(因为数组队列,在出队的时候,我们往往要将数组中的元素往前挪动一个位置,这个动作的时间复杂度O(n ...

  6. 第七周--数据结构--队列数组

     /*    *第七周--数据结构--队列数组     *Copyright (c) 2015 烟台大学计算机与控制工程学院    *All right reserved.    *文件名称:li ...

  7. 数据结构-队列和栈有什么区别

    数据结构-队列和栈有什么区别 1:队列和栈是两种不同的数据结构.它们有以下区别: (1)操作的名称不同.队列的插入称为入队,队列的删除称为出队.栈的插入称为进栈,栈的删除称为出栈. (2)可操作的方式 ...

  8. 数据结构——队列的C语言代码实现

    系列文章目录 数据结构--顺序表的C语言代码实现 数据结构--八种链表的C语言代码实现 数据结构--栈的C语言代码实现 数据结构--队列的C语言代码实现 数据结构--堆的C语言代码实现 文章目录 系列 ...

  9. 数据结构——队列 c++详解

    1.队列(Queue)与栈一样,是一种线性存储结构,它具有如下特点: (1)队列中的数据元素遵循"先进先出"(First In First Out)的原则,简称FIFO结构: (2 ...

最新文章

  1. 面试官:啥是集群策略啊?
  2. Android float 四舍五入没有入的一个问题
  3. 动态规划/贪心总结(一)
  4. vue怎么给html元素加类选择器,Vue.js——获取Dom对象的类选择器名(className)
  5. javafx查找子节点_JavaFX技巧29:使布局忽略不可见的节点
  6. java获取主机mac_Java 如何获取主机的MAC地址
  7. cmd控制远程电脑运行程序_电脑远程控制怎么,远程桌面开启教程
  8. html一个页面多个动画,如何在单个html页面中添加两个相同的adobe边缘动画?
  9. php 远程连接 sqlserver,Linux下PHP远程连接SqlServer数据库
  10. Java 10 var关键字详解和示例教程
  11. IT民工系列——c#控制Word的类库。对com操作进行了封装
  12. 仿微信实现拍摄视频,实现点击无声,自动录制
  13. python爬虫qq音乐_Python爬虫-QQ音乐无损音乐地址解析
  14. 计算机应用结课PPT,计算机应用说课.ppt
  15. 【历史上的今天】2 月 23 日:英格玛密码机申请专利;戴尔电脑创始人出生;Mellanox 收购 EZchip
  16. 【数据分析】:搭建数据分析业务工作流程
  17. 转: RGB565、RGB888互相转换原理和代码
  18. ios微信小程序虚拟支付解决办法
  19. tensorflow基本知识
  20. 熟悉使用工具---第二次作业

热门文章

  1. python各种模块,迭代器,生成器
  2. JavaSe基础2022年12月05日学习内容
  3. 丝雨学姐小灶班——Week7
  4. 在一个js函数里面获取另一个js函数的变量
  5. V831——人脸识别通过串口向下位机发送指令
  6. 移动端,录音之前判断是否已经获取录音权限
  7. Godex科诚条码打印机编程
  8. 基于Miniblink的WebBrowser控件CXMBWebCtrl及简单的浏览器Demo
  9. 你知道Application吗?
  10. 百度空间迁入新家百度云