概念:队列是限定只能在表的一端进行插入在另一端进行删除操作。在表中,允许插入的一端称为“队列尾”,允许删除的另一端称为“对列尾”
顺序队列:
定义:概念:队列的顺序存储结构为顺序队列,顺序队列实际上是运算受限的顺序表
顺序队列的表示:1.和顺序表一样,顺序队列用一个向量空间来存放当前队列中的元素
2.由于队列的队头和队尾的位置时变化的,设置俩个指针front和rear分别指示队头元素和队尾元素在向量空间中的位置,它们的初值再队列初始化时均应置为0,表示队列为空
顺序队列的基本操作:1.入队时:将新元素插入rear所指的位置,然后将rear加1
2.出队时:删去front所指的元素,然后将front加1并返回被删除元素
注意:
1.当头尾指针相等时,队列为空
2.在非空队列里,队头指针始终指向队头元素,指针始终指向下一个元素的下一个
顺序队列的溢出现象:1.“下”溢现象,当队列为空时,作出队运算产生的溢出现象,“下溢”常用作程序控制转移的条件
2.“真上溢”现象,当队列满时,做入队运算产生空间溢出的现象。“真上溢”是一种出错状态,要设法避免
3.“假上溢”:由于入队和出队操作中,头尾指针只指向后增加不减小,致使出队元素的空间永远无法重新利用。当队列实际的元素个数远远小于空间的规模,但可能由于队尾指针已超越空间的上界,没有空间。
循环队列:为充分利用空间,克服“假上溢”现象的方法是:将空间想象为一个首尾相接的圆环,存储在其中的队列称为循环队列。
循环队列的基本操作:循环队列中进行出队,入队操作时,头尾指针仍要加1,向后移动,只不过当队尾指针指向空间上界时,其加1操作的结果是指向向量的下界0,即循环回到头部,这种循环意义下加1操作可以描述为:
1.未超越循环队列的长度时,指针加1
if(i+1==queueSize)
i= 0;
else
i++;
2.超越循环队列的长度时,利用“模运算”,将指针指向头部
i = (i+1)%queueSize;
循环队列的边界条件处理:循环队列由于入队时队尾指针向前追赶队首指针;出队时队首指针向前追赶队尾指针,队首队尾指针指向相同位置时,无法区分是队空还是队满,无法通过件front==rear来判别队列是空还是满。
1.单独设置一个布尔变量以区别队列的空和满
2.浪费一个元素的空间。规定入队操作前,先测试队尾指针在循环意义下加1后是否等于头指针,若相等则认为满队
3.使用一个计数器记录队列中元素的总数,通过队列长度和队列的容量大小,判断是否越界。
#define _CRT_SECURE_NO_WARNINGS
#include<iostream.h>
template <class T>
class SeqQueue // 顺序循环队列类
{
private:
T *element; //动态数组存储队列的数据元素
int size;
int front,rear;
public:
SeqQueue(int size=64); //构造指定容量的空队列
~SeqQueue();
bool isEmpty(); //判断是否为空
void enqueue(T x); //入队
T dequeue(T x); //出队,返回队头元素。若队列空则抛出异常
friend ostream& operator <<(ostream& out, SeqQueue<T>&que);
};
template<class T>
SeqQueue<T>::SeqQueue(int size)
{
this->size = size<64?64:size;
element = new T [this->size];
front = rear =0;
}
template <class T>
SeqQueue<T>::~SeqQueue()
{
delete []element;
}
template<class T>
bool SeqQueue<T>::isEmpty()
{
return front == rear;
}
template <class T>
void SeqQueue<T>::enqueue(T x) //入队
{
if(front == (rear+1)%size)
{
T *temp =element;
element = new T [size*2]; // 重新申请一个容量更大的数组
int i=front, j=0;
while(i!=rear)
{
element[j]=temp[i];
i=(i+1)%size;
j++;
}
front = 0;
rear = j;
size *=2;
}
element[rear] = x;
rear = (rear+1)%size;
}
template<class T>
T SeqQueue<T>::dequeue()
{
if(!isEmpty())
{
T x =element[front];
front = (front + 1)%size;
return x;
}
throw "空队列,不能执行出队操作";
}
template<class T>
ostream& operator <<(ostream& out, SeqQueue<T>&que)
{
out<<"SeqQueue:(";
int i=que.front;
while(i!que.rear)
{
out<<que.element[i]<<" ";
i=(i+1)%que.size;
}
out<<")"<<endl;
return out;
}
链式队列:链式队列和单链表一样,可以附加一个头结点,真正的队头元素并非在队头指针所指的结点中,而在队头指针所指的后继结点中。也可以用不带头结点的单链表实现。
#include<iostream.h>
#include "Node.h"
template<class T>
class LinkedQueue
{
private:
Node<T> *front,*rear;
public:
LinkedQueue();
~LinkedQueue();
bool isEmpty();
void enqueue(T x);
T dequeue();
friend ostream&operator<<(ostream& out,LinkedQueue<T>&que);
};
template<class T>
LinkedQueue<T>::LinkedQueue()
{
front = rear =NULL;
}
template <class T>
LinkedQueue<T>::~LinkedQueue()
{
Node<T> *p=front,*q;
while(p!=NULL)
{
q=p;
p=p->next;
delete q;
}
front = rear=NULL;
}
template<class T>
bool LinkedQueue<T>::isEmpty ()
{
return front==NULL&&rear==NULL;
}
template<class T>
void LinkedQueue<T>::enqueue(T x)
{
Node<T> *q =new Node<T>(x);
if(isEmpty())
front =q;
else
rear->next=q;
rear = q;
}
template<class T>
T LinkedQueue<T>::dequeue()
{
if(!isEmpty())
{
T x=front->data;
Node<T> *p=front;
front = front->next;
delete p;
if(front==NULL)
rear = NULL;
return x;
}
throw "空队列不能执行出队操作";
}
template <class T>
ostream& operator<<(ostream& out,LinkedQueue<T>&que)
{
out<<" LinkedQueue: (";
Node<T> *p=que.front;
while(p!=NULL)
{
out<<p->data;
p=p->next;
if(p!=NULL)
cout<<",";
}
out<<")"<<endl;
return out;
}
打印杨辉三角:
#define _CRT_SECURE_NO_WARNINGS
#include<stdlib.h>
#include<iostream>
#include "SeqQueue.h"
void yanghui(int n)
{
int s,e; //打印出杨辉三角的前n行
SeqQueue<int> *sq = new SeqQueue<int> (n+2);
for(int i = 1;i<=n;i++)
cout<<' ';
cout<<'1'<<endl; //在中心位置输出杨辉三角的1
sq->enqueue(0); //添加行界值
sq->enqueue(1);
sq->enqueue(1); //第一行值输入队列
int k = 1;
while(k<n)
{ //通过循环队列输出前n-1行的值
for(i = 1;i<=n-k;i++)
cout<<' ';//输出n-k个空格以保持杨辉三角
sq->enqueue(0); //行界值“0”入队列
do{
s=sq->dequeue();
e=sq->getHead();
if(e) cout<<e<<' ';//若e为非行界值,则打印输出e的值并加一空格
else cout<<endl; // 否则回车换行,为下一行输出做准备
sq->enqueue(s+e);
}while(e!=0)
k++;
}
}
int main()
{
int s;
cout<<"请输入整数:"<<endl;
cin>>s;
yanghui(s);
return 0;
}