C++实现普通队列,循环队列的基本操作(初始化,入队,出队,获取队列首元素等)
来源:互联网 发布:前端优化14个性能规则 编辑:程序博客网 时间:2024/04/24 04:28
队列是一种先进先出(FIFO,First-In-First-Out)的线性表,通常用链表或者数组来实现。队列只能在队尾插入元素,只能在队首删除元素。
队列的一些性质:
1.出队方案唯一
2.队首元素先出
3.新元素插入队尾
线性队列的初始化:
#include <iostream>using namespace std;class Queue{private: int *data; //定义指向整型的指针,从而动态开辟内存 int head,tail,length; //head指向队首,tail指向队尾,length表示队列的长度public: Queue (int length_input){ //构造函数,对新声明的队列对象进行初始化 data = new int [length_input]; //动态开辟100个整型数据的空间 length = length_input; //为队列的长度赋初始值 head = 0; //起初head为0,表示head值未改变的情况下,一直指向首元素 tail = -1; //tail初始值为-1,表示此时队列为空,无任何数据元素 } ~Queue(){ delete [] data; //析构函数,删除动态开辟的内存 }};int main() { Queue queue(100); //声明一个队列对象,并初始化 return 0;}入队操作:
#include <iostream>using namespace std;class Queue{private: int *data; //定义指向整型的指针,从而动态开辟内存 int head,tail,length; //head指向队首,tail指向队尾,length表示队列的长度public: Queue (int length_input){ //构造函数,对新声明的队列对象进行初始化 data = new int [length_input]; //动态开辟100个整型数据的空间 length = length_input; //为队列的长度赋初始值 head = 0; //起初head为0,表示head值未改变的情况下,一直指向首元素 tail = -1; //tail初始值为-1,表示此时队列为空,无任何数据元素 } ~Queue(){ delete [] data; //析构函数,删除动态开辟的内存 } void push(int element){ //入队操作,只能从队列的尾部插入数据元素 if(tail+1 < length){ //队列未满的时候才能插入,否则则插入失败 ++tail; //队尾指针先往后移动一位 data[tail] = element; //再插入队尾指针指向的位置 } } void output(){ for(int i = head;i <= tail;i++){ //从队首一直遍历到队尾 cout << data[i] << " "; } cout << endl; }};int main() { Queue queue(100); //声明一个队列对象,并初始化 for(int i = 1;i <= 10;++i){ queue.push(i); //将1-10这10个数据元素依次插入队列中 } queue.output(); //调用输出的方法 return 0;}效果图:
出队以及获取队首元素的操作:
#include <iostream>using namespace std;class Queue{private: int *data; //定义指向整型的指针,从而动态开辟内存 int head,tail,length; //head指向队首,tail指向队尾,length表示队列的长度public: Queue (int length_input){ //构造函数,对新声明的队列对象进行初始化 data = new int [length_input]; //动态开辟100个整型数据的空间 length = length_input; //为队列的长度赋初始值 head = 0; //起初head为0,表示head值未改变的情况下,一直指向首元素 tail = -1; //tail初始值为-1,表示此时队列为空,无任何数据元素 } ~Queue(){ delete [] data; //析构函数,删除动态开辟的内存 } void push(int element){ //入队操作,只能从队列的尾部插入数据元素 if(tail+1 < length){ //队列未满的时候才能插入,否则则插入失败 ++tail; //队尾指针先往后移动一位 data[tail] = element; //再插入队尾指针指向的位置 } } void pop(){ if(tail < 0){ //队列为空,出队失败 return; } ++head; //队首指针后移,表示原来队首已出列 } int top(){ if(tail > -1){ //队列不为空的情况下才能获取队首元素 return data[head]; } } void output(){ for(int i = head;i <= tail;i++){ //从队首一直遍历到队尾 cout << data[i] << " "; } cout << endl; }};int main() { Queue queue(100); //声明一个队列对象,并初始化 for(int i = 1;i <= 10;++i){ queue.push(i); //将1-10这10个数据元素依次插入队列中 } queue.output(); //调用输出的方法 cout << "当前的队首元素为:" << queue.top() << endl; queue.pop(); //出队 queue.output(); //调用输出的方法 cout << "出队操作后的队首元素为:" << queue.top() << endl; return 0;}效果图:
可是,普通队列有什么局限性呢?比如说我们动态申请了能够100个整型数据的数组来容纳队列中的元素,而正如函数中的判断语句:
tail+1 >= length
当tail的值达到length-1时,实际上就说明“队列”已经满了。但是实际情况真的是如此吗?
比如说在队列操作的过程中,不断地有元素出队,而且不断地有元素入队,那么的话,当tail的值达到length-1时,实际上就说明“队列”已经满了,但是如果此时head的值不是0的话,实际上这个队列是没有装满100个数据元素的,head之前的空间都将会被浪费。这种现象在我们程序设计中,称作“假溢出”现象
假溢出:系统作为队列用的存储区还没有满,但队列却发生了溢出,我们把这种现象称为"假溢出"。
假溢出百度百科描述
我们这时候肯定会想,如果这时候队尾指针tail能够继续越过队尾,往0—head之间增添元素的话,那么就可以避免空间的浪费了,所以呢,基于这种想法,我们便引进了循环队列来对当前队列进行改进
循环队列,顾名思义,就是以循环的方式来存储队列。回顾一下我们之前用到的队尾标记 tail。对于循环队列,当队尾标记 tail 到达数组的上界后,如果队列内的元素个数没有达到容量上限,就跳转到数组的起始位置,也就是 0 的位置;队首标记 head 到达数组上界采取同样的处理。通过这样的方法,我们就能够最大化利用内存空间,避免“假上溢”的情况出现啦。
循环队列:
下面我们将改进线性队列的代码,实现循环队列的一些基本操作
循环队列的一些性质:
1.在循环队列里,如果容量没有达到上限,当队尾队首标记达到数组上界后,就跳转到数组起始位置
2.在线性队列里,当 tail 达到队列上限后,继续插入就会发生“假上溢”的情况
3.循环队列里可通过统计队列里元素个数,判断能否继续往队列里插入元素
首先,我们增加一个count变量来计算入队的元素个数,这样的话,当count = length的时候,才表示真正的队列“上溢”,所以呢,对于循环队列的入队操作,可分两种情况讨论:
1.如果队尾指针此时并未指向队列的最后一位,那么队尾指针直接前移
2.当队尾指针此时指向最后一位时,那么当队列未满时,则队尾指针将跳转至数组起始位置
第一种情况下,我们可以写成:
tail = tail + 1;而第二种情况下,我们可以写成:
tail = (tail + 1)% length所以呢,两种情况综合起来,则可写成:
tail = (tail + 1) % length;同样的,出队操作时,则有:
head = (head + 1) % length;这里特别需要注意的是,循环队列的遍历输出时,循环截止条件不再是head <= tail,而是head != tail +1,这是为什么呢?原因其实也很简单,因为当队尾队首标记达到数组上界后,就跳转到数组起始位置,所以tail是可能小于head的,而无论是head<tail,亦或是head > tail,都是顺时针从head循环至tail,所以可用此循环截止条件:
for(int i = head;i != tail + 1;i = (i + 1)%length){ //从队首一直遍历到队尾,当遍历到最后一位时,跳转至数组起始位置 //特别注意此时循环截止的条件应该是i != tail + 1,因此可能tail的值小于head cout << data[i] << " "; }循环队列初始化,入队出队等操作完整代码实现:
#include <iostream>using namespace std;class Queue{private: int *data; //定义指向整型的指针,从而动态开辟内存 int head,tail,length,count; //head指向队首,tail指向队尾,length表示队列的长度,count用于记录队列中元素个数,从而判断队列是否已满public: Queue (int length_input){ //构造函数,对新声明的队列对象进行初始化 data = new int [length_input]; //动态开辟100个整型数据的空间 length = length_input; //为队列的长度赋初始值 head = 0; //起初head为0,表示head值未改变的情况下,一直指向首元素 tail = -1; //tail初始值为-1,表示此时队列为空,无任何数据元素 count = 0; } ~Queue(){ delete [] data; //析构函数,删除动态开辟的内存 } void push(int element){ //入队操作,只能从队列的尾部插入数据元素 if(count < length){ //队列未满的时候才能插入,否则则插入失败 tail = (tail + 1) % length; //分两种情况,如果队尾指针此时并未指向队列的最后一位,那么队尾指针直接前移,而当队尾指针此时指向最后一位时 data[tail] = element; //那么当队列未满时,则队尾指针将跳转至数组起始位置,再将数据元素插入队尾指针指向的位置 ++count; //入队成功,队列中元素数量加一 } } void pop(){ if(count < 0){ //队列为空,出队失败 return; } head = (head + 1) % length; //同样,根据循环队列的性质得出 --count; //出队成功,队列中元素数量减一 } int top(){ if(count > 0){ //队列不为空的情况下才能获取队首元素 return data[head]; } } void output(){ for(int i = head;i != tail + 1;i = (i + 1)%length){ //从队首一直遍历到队尾,当遍历到最后一位时,跳转至数组起始位置 //特别注意此时循环截止的条件应该是i != tail + 1,因此可能tail的值小于head cout << data[i] << " "; } cout << endl; }};int main() { Queue queue(100); //声明一个队列对象,并初始化 for(int i = 1;i <= 10;++i){ queue.push(i); //将1-10这10个数据元素依次插入队列中 } queue.output(); //调用输出的方法 cout << "当前的队首元素为:" << queue.top() << endl; queue.pop(); //出队 queue.output(); //调用输出的方法 cout << "出队操作后的队首元素为:" << queue.top() << endl; return 0;}
效果图:
如有错误,还请指正,O(∩_∩)O谢谢
- C++实现普通队列,循环队列的基本操作(初始化,入队,出队,获取队列首元素等)
- 循环队列的初始化、入队、出队等基本操作
- C语言实现循环队列基本操作(初始化、判断队空、入队、出队)
- 链队列、循环队列的实现(初始化、出队、入队、取队头元素、判空)
- 链队列的初始化、入队、出队等操作实现
- C语言实现顺序队列的初始化、入队、出队等操作(三)
- 循环队列的综合操作(出入队、获取队长度)C语言实现
- 队列的入队、出队基本操作
- 采用顺序存储实现循环队列的初始化、入队、出队操作。
- 顺序队列基本操作的实现----入队、出队、打印
- 队列的入队、出队操作实现
- 循环队列的定义、入队、出队等操作 C++代码实现
- [转载] 循环队列的定义、入队、出队等操作 C++代码实现
- 循环队列的操作(初始化,入队,出对,销毁,输出)
- 数据结构之队列的基本操作入队出队初始化删除-c++代码实现
- 链队列的简单操作(入队,出队,输出队元素等)
- 链式队列操作,初始化,入队,出队
- 【C++】容器适配器实现队列Queue的各种功能(入队、出队、判空、大小、访问所有元素等)
- Java对象的序列化和反序列化
- 二叉树拷贝
- MyBatis传入参数为集合 list 数组 map写法
- UVa 232, Crossword Answers
- POJ--3169 Layout
- C++实现普通队列,循环队列的基本操作(初始化,入队,出队,获取队列首元素等)
- tableview刷新某个分区或者某行
- 最基本的‘*’号图形打印---菱形
- HDU 5018 Revenge of Fibonacci
- iPhone开发之实现UITableView多选删除功能详解
- MFC消息机制---消息映射
- MySql的一道小练习
- HDU 5019Revenge of GCD
- POJ 3904