队列的实现:顺序队列

队列也是一种常见的线性表,它和栈相比有以下不同:

  1. 队列可以在表的两端进行操作。栈只能在栈顶进行插入和删除。
  2. 两端允许操作的类型不一样:可以进行删除的一端称为队头,这种操作也叫出队;可以进行插入的一端称为队尾,这种操作也叫入队。总的来说,队头只能出队,队尾只能入队。

队列的示意图:

模拟队列这种数据结构并不是什么难事,但会遇到一些问题,如:

假溢出

队列中明明还有空间,却因为rear已经指向最后,造成无法入队问题,这是假溢出。

解决办法是:使用链式存储,这显然可以。在顺序存储时,我们常见的解决办法是把它首尾相接,构成循环队列,这可以充分利用队列的存储空间。

循环队列示意图:

在上图中,front指向队列中第一个元素,rear指向队列队尾的下一个位置。

但依然存在一个问题:当front和rear指向同一个位置时,这代表的是队空还是队满呢?大家可以想象下这种情景。

解决这种问题的常见做法是这样的:

  1. 使用一标记,用以区分这种易混淆的情形。
  2. 牺牲一个元素空间。当front和rear相等时,为空;当rear的下一个位置是front时,为满。

如下图:

下面我们给出循环队列,并采用第二种方式,即牺牲一个元素空间来区分队空和队满的代码.

几个重点:

  1. front指向队头,rear指向队尾的下一个位置。
  2. 出队时,front=(front+1)%MAXSIZE;入队时,rear=(rear+1)%MAXSIZE。
  3. 队为空的判断:front==rear;队为满的判断:(rear+1)%MAXSIZE==front。

代码:

类定义

#include<iostream>
#include<queue>
#include<iomanip>
using namespace std;
#define MAXSIZE 10
typedef int ElemType;
//类定义
class SqQueue   //顺序队列
{
	private:
	ElemType *base;
	int front;   //队头指针
	int rear;    //对尾指针
	public:
	SqQueue();   //构造函数
	~SqQueue();  //析构函数
	void clear();   //请空队列
	bool empty();   //队列是否为空
	int size();     //获取队列大小
	bool push(const ElemType &);    //入队,队为满,返回false
	bool pop();     //出队,队为空,返回false
	const ElemType top();    //获取队头元素
	const ElemType back();     //获取队尾元素
	void queueTraverse();   //队列的遍历
};
//类实现
SqQueue::SqQueue()   //构造函数
{
	base=new ElemType[MAXSIZE];
	front=rear=0;
}
SqQueue::~SqQueue()   //析构函数
{
	delete[]base;
}
void SqQueue::clear()   //请空队列
{
	rear=front;
}
bool SqQueue::empty()    //队列是否为空
{
	return front==rear;
}
int SqQueue::size()   //获取队列大小
{
	return (rear-front+MAXSIZE)%MAXSIZE;
}
bool SqQueue::push(const ElemType &data)   //入队,队为满,返回false
{
	/*
		另一种判断队满的方法
		size() == MAXSIZE;
	*/
	if((rear+1)%MAXSIZE==front)   //队满判断
	return false;
	base[rear]=data;
	rear=(rear+1)%MAXSIZE;
	return true;
}
bool SqQueue::pop()    //出队,队为空,返回false
{
	if(empty())
	return false;
	front=(front+1)%MAXSIZE;
	return true;
}
const ElemType SqQueue::top()    //获取队头元素
{
	if(empty())
	{
		cerr<<"队空!"<<endl;
		exit(0);
	}
	else
	return base[front];
}
const ElemType SqQueue::back()     //获取队尾元素
{
	if(empty())
	{
		cerr<<"队空!"<<endl;
		exit(0);
	}
	return
	base[(rear-1+MAXSIZE)%MAXSIZE];
}
void SqQueue::queueTraverse()   //队列的遍历
{
	if(empty())
	cout<<"队空,无法遍历!"<<endl;
	else
	{
		int p=front;
		while(p!=rear)
		{
			cout<<setw(4)<<base[p];
			p=(p+1)%MAXSIZE;
		}
		cout<<endl;
	}
}

主函数

int main()
{
	cout<<"循环顺序队列演练"<<endl;
	SqQueue queue;
	ElemType data;
	printf("入队,输入0结束!\n");
	while(cin>>data && data)
	{
		if(!queue.push(data))
		{
			printf("队已满,无法入队了!\n");
			break;
		}
	}
	cout<<"遍历"<<endl;
	queue.queueTraverse();
	cout<<"获取队头元素 "<<queue.top()<<endl;
	cout<<"获取队尾元素 "<<queue.back()<<endl;
	data=77;
	cout<<"队头出队,"<<data<<" 入队。"<<endl;
	queue.pop();
	queue.push(data);
	cout<<"遍历"<<endl;
	queue.queueTraverse();
	cout<<"再次入队"<<endl;
	while(cin>>data && data)
	{
		if(!queue.push(data))
		{
			printf("队已满,无法入队了!\n");
			break;
		}
	}
	cout<<"遍历"<<endl;
	queue.queueTraverse();
	cout<<"队清空后,是否为空:";
	queue.clear();
	queue.empty()?cout<<"Yes!"<<endl:cout<<"No!"<<endl;
	cout<<"清空后,遍历"<<endl;
	queue.queueTraverse();
	cout<<"获取队头元素:";
	queue.top();
	system("pause");
	return 0;
}

运行:

完整代码下载:队列的实现:顺序队列

队列的实现:顺序队列

时间: 2024-09-29 19:43:16

队列的实现:顺序队列的相关文章

队列学习笔记 顺序队列

//顺序队列操作 #define QUEUEMAX 15 typedef struct  { DATA data[QUEUEMAX]; // 队列数组  int head;   //队头  int tail;   // 队尾   } SeqQueue; SeqQueue *SeqQueueInit() { SeqQueue *q; if(q=(SeqQueue *)malloc(sizeof)(SeqQueue))   // 申请保存队列的内存  { q->head = 0;  // 设置队头 

顺序队列和链式队列的实现

队列是一种常用的数据结构,它跟栈一样,操作都受到限制,队列只允许从一端进数据,另一端出数据.队列跟栈不同,栈是一种"后进先出"的模式,而队列是一种"先进先出"的操作模式.就好比日常排队一样,先排队的先出,后排队的后出.例如,进入队列的顺序是1,2,3,4,5则出队列的顺序是1,2,3,4,5(只考虑一次性出列的情况). 队列也分顺序队列和链式队列,跟顺序栈和链表栈一样,顺序队列同样是基于数组实现,链式队列则是基于链表实现. 顺序队列: //顺序队列 #include

数据结构(C实现)------- 顺序队列(循环队列之计数器实现)

为了能充分的利用空间,解决顺序队列的"假溢出"问题,可以采用两种方法:一种是将数据向前移动,让空的存储单元留在队尾:另一种是将顺序队列构造成一个环状的空间,即将队列的数据区data[0....MAXSIZE-1]看成头尾相接的循环结构,使得data[0]接在data[MAXSIZE-1]之后,这就是循环队列. 这节就来实现循环顺序队列. 循环队列中的空闲的空间可以被利用,除非数组空间真的被队列元素全部占用,否则不会上溢.因此,队一此简单的应用外,真正实用的顺序队列是循环队列. 入队时,

顺序队列(Sequential Queue)

顺序队列(Sequential Queue) 1. 顺序队列的概念 1.1 顺序队列的定义 顺序队列是基于数组的存储表示实现的队列. 1.2 顺序队列中各元素的逻辑及存储关系 顺序队列可以采用顺序表作为其存储表示,因此,可以在顺序队列的声明中用顺序表定义它的存储空间. 顺序队列可以使用一维数组作为队列的存储空间,存放队列元素的数组的头指针为*elements,该数组的最大允许存放元素个数为maxSize,当前队列的队头位置由数组下标指针front指示,队尾位置由数组下标指针rear指示,如果队列

数据结构Java实现07----队列:顺序队列&amp;顺序循环队列、链式队列、顺序优先队列

数据结构Java实现07----队列:顺序队列&顺序循环队列.链式队列.顺序优先队列 一.队列的概念: 队列(简称作队,Queue)也是一种特殊的线性表,队列的数据元素以及数据元素间的逻辑关系和线性表完全相同,其差别是线性表允许在任意位置插入和删除,而队列只允许在其一端进行插入操作在其另一端进行删除操作. 队列中允许进行插入操作的一端称为队尾,允许进行删除操作的一端称为队头.队列的插入操作通常称作入队列,队列的删除操作通常称作出队列. 下图是一个依次向队列中插入数据元素a0,a1,...,an-

顺序队列实现任务以此执行-任务调度系列2

顺序队列实现任务以此执行的想法: public class TaskManage { //任务队列 private BlockingQueue<Runnable> queue = new ArrayBlockingQueue<Runnable>(10); private boolean running = false; public void start() { running = true; Thread t = new Thread(new OrderedJob()); t.s

数据结构6_顺序队列(循环队列)

本文实现了顺序队列,与链队列不同的是,顺序队列需要考虑一个问题, 问题情况如下, 解决办法:循环队列,当rear到分配的数组空间末尾时,转到数组头 但是当q.rear==q.front时,又如何区分一种是空队列,一种是满队列的情况呢 这里有两种方案 本次代码实现了第一种方法,同时设置了一个技术变量length,稍加改动便可实现第二个方法 代码如下: #include<iostream>using namespace std;//该顺序队列为循环队列,解决队尾指针达到最大值,队列中有空闲单元,但

【小白成长撸】--循环顺序队列

1 // 循环顺序队列.cpp : 定义控制台应用程序的入口点. 2 //适合整数 3 4 #include "stdafx.h" 5 #include<stdio.h> 6 7 #define MAXNUM 100 8 #define true 1 9 #define false 0 10 11 typedef struct queue_type 12 { 13 int queue[MAXNUM];//队列的最大值为100 14 int front;//头指针 15 in

数据结构(C实现)------- 顺序队列(循环队列之少用一个存储空间实现) .

上节已经提到有三种方法来实现循环顺序队列,其中第一种设立标识不常用,最常的就是后两种,上一节已经讨论了用计数器来实现循环顺序队列,这节就用第三种方法,也就是少用一个存储空间来实现循环顺序队列,其基本操作和用计数实现类同,下面是具体实现: 顺序队列(循环队列)类型描述: //顺序队列的类型描述 #define MAXSIZE 5 typedef int ElemType; typedef struct{ ElemType *data; int front,rear; }SqQueue; 基本操作:

顺序队列总结

基本数据结构之-顺序队列 顺序队列就是对开辟在堆上的一段连续空间的操作 队列有入队和出队的操作,如果把开始的位置作为队头,那么在入队的时候需要移动数据,如果把末尾做为队头,在出队的时候需要移动元素,所以使用哪种方法都没有简单的, 其实可以指定两个参数来标记队列中队头和对尾的位置,但是在入队和出队的时候就需把这种情况考虑进去.(其实这就成了循环队列了,哈哈) 今天还是写顺序队列吧 //分析需要一个容量(因为需要动态的开辟空间来存储数据) // 需要一个长度来记录当前数据的长度 typedef st