队列

一、队列概念

队列(Queue)也是一种限定存取位置的线性表。它只允许在表的一端插入,而在另一端删除。允许插入的一端称为队尾(rear),允许删除的一端叫做队头(front)。

二、顺序队列

每次在队尾加入新元素,a0最先加入,an-1最后加入。加入称为进队,删除称为出队。a0最先出队,就像排队登机一样。队列的这种特性正好与栈相反,叫做先进先出FIFO(First In First Out)。
特点:随队尾加入元素,队尾(rear)不断向后移;而随队头元素的出队,则队头(front)也不断后移,即位置都可以改变。

顺序队列:

#include<cassert>
#include<iostream>
using namespace std;
template<typename T>class Queue
{
	int rear,front; //队尾与队头
	T *elements; //存放队列元素的容器
	int maxSize; //队列最多可容纳元素个数+1
public:
	Queue(int ms=18);//默认最多存放17个元素,因为要空出一个
	~Queue(){delete[] elements;}
	bool IsEmpty() const {return front==rear;} //判断队是否空
	bool IsFull() const {return (rear+1)%maxSize==front;} //判断队是否满
	int Length() const {return (rear-front+maxSize)%maxSize;}
	//求队中元素数,注意:求余算法是实现循环队列的基础算法
	void EnQue(const T &data); //进队
	T DeQue(); //出队
	T GetFront(); //取队头数据
	void MakeEmpty(){front=rear=0;} //队置空(初始态)
};
template<typename T> Queue<T>::Queue(int ms)
{
	maxSize=ms;
	elements=new T[maxSize];
	rear=front=0;
	assert(elements!=NULL); //断言:分配成功
}
template<typename T> void Queue<T>::EnQue(const T &data)
{ //进队
	assert(!IsFull()); //断言:队列不满,不满才能进队
	rear=(rear+1)%maxSize; //队尾指针加1
	elements[rear]=data;
}
template<typename T>T Queue<T>::DeQue()
{
	assert(!IsEmpty());
	front=(front+1)%maxSize; //队头指针加1
	return elements[front]; //注意front指向现在队头的前一位置
}
template<typename T>T Queue<T>::GetFront()
{
	assert(!IsEmpty());
	return elements[(front+1)%maxSize]; //注意加1才能返回队头数据
}
int main()
{
	int i;
	Queue<char> que; //默认为18元素队列,可用17个元素,包括串结束符
	char str1[]="abcdefghijklmnop";  //17个元素,包含\0
	que.MakeEmpty();
	for(i=0;i<17;i++) que.EnQue(str1[i]);
	if(que.IsFull()) cout<<"队满";
	cout<<"共有元素:"<<que.Length()<<endl;
	for(i=0;i<17;i++) cout<<que.DeQue(); //先进先出
	cout<<endl;
	if(que.IsEmpty()) cout<<"队空";
	cout<<"共有元素:"<<que.Length()<<endl;
	return 0;
}

这里必须注意,空队时rear=front,而满队时必须空一个位置,不然空与满就分不清楚了。浪费一个位置好像太可惜,但是若想利用这个空间,必须加一个标志来表示队空/队满,进队出队都要判断,使用上更不方便。

三、链队列

与链栈一样,同样可以有链队。在链首出队,在链尾入队。与链栈一样,链队这里也用无链表头结点方式。链队不需要循环方式。

链队列

#include<iostream>
#include<cassert>
using namespace std;
template<typename T>class Queue;
template<typename T>class Node
{
	T info;
	Node *link; //在类模板Node中使用指向Node的指针可以不加<T>
public:
	Node(T data=0,Node *Link=NULL);
	friend class Queue<T>;
};
template<typename T> Node<T>::Node(T data,Node *Link)
{
	info=data;
	link=Link;
}
template<typename T>class Queue
{
	Node<T> *front,*rear; //在其他类中指向Node的指针必须加<T>
public:
	Queue(){rear=front=NULL;} //构造一个空链队
	~Queue();
	bool IsEmpty(){ return front==NULL;} //队是否是空的?
	void EnQue(const T &data); //进队
	T DeQue(); //出队
	T GetFront(); //查看队头数据
	void MakeEmpty(); //置空队列,与析构逻辑上不同,物理上一样
};
template<typename T>void Queue<T>::MakeEmpty() //相当于析构函数
{
	Node<T> *temp;
	while(front!=NULL)
	{
		temp=front;
		front=front->link;
		delete temp;
	}
	//从头到尾清空队列,最后front=rear=NULL
}
template<typename T>Queue<T>::~Queue(){MakeEmpty();}
template<typename T>void Queue<T>::EnQue(const T &data)
{
	if(front==NULL) front=rear=new Node<T>(data,NULL);//第一次进队
	else rear=rear->link=new Node<T>(data,NULL); 
	//链队向后生成,新入队者在队尾
}
template<typename T>T Queue<T>::DeQue()
{
	assert(!IsEmpty());
	Node<T> *temp=front;
	T data=temp->info; //取队头结点中的数据
	front=front->link; //队头出队
	delete temp; //释放内存空间
	return data;
}
template<typename T>T Queue<T>::GetFront()
{
	assert(!IsEmpty());
	return front->info;
}
int main()
{
	int i;
	Queue<char> que; //构造一个空链队
	char str1[]="abcdefghijklmnop"; //17个元素,包括串结束符\0
	for(i=0;i<17;i++) que.EnQue(str1[i]);
	for(i=0;i<17;i++) cout<<que.DeQue(); //先进先出
	cout<<endl;
	if(que.IsEmpty()) cout<<"队空"<<endl;
	return 0;
}

注意:
这里调用 assert() 函数,其调用基本格式是:

#include<cassert>
assert(int expression);
  • 如果expression的结果为0(条件不成立),那么它先向stderr打印一条出错信息,然后通过调用 abort() 来终止程序运行。
  • 如果expression的结果为非 0(条件成立),那么断言成功,表明程序正确,assert() 不进行任何操作。

大部分编译器打印出错格式为:
Assertion failed: expression, file filename, line number

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值