链队列
1、 链队列的定义
队列的链式存储结构简称为链队列。它是限制仅在表头删除和表尾插入的单链表。
2、 链队列的结构类型说明
注意:
增加指向链表上的最后一个结点的尾指针,便于在表尾做插入操作。
链队列示意图见上图,图中Q为LinkQueue型的指针。
3、 链队列的基本运算
(1) 置空队
void InitQueue(LinkQueue *Q)
{
Q->front=Q->rear=NULL;
}
(2) 判队空
intQueueEmpty(LinkQueue *Q)
{
return Q->front==NULL&&Q->rear==Null;
//实际上只须判断队头指针是否为空即可
}
(3) 入队
void EnQueue(LinkQueue *Q,DataType x)
{//将元素x插入链队列尾部
QueueNode *p=(QueueNode *)malloc(sizeof(QueueNode));//申请新结点
p->data=x; p->next=NULL;
if(QueueEmpty(Q))
Q->front=Q->rear=p; //将x插入空队列
else { //x插入非空队列的尾
Q->rear->next=p; //*p链到原队尾结点后
Q->rear=p; //队尾指针指向新的尾
}
}
(4) 出队
DataType DeQueue (LinkQueue *Q)
{
DataType x;
QueueNode *p;
if(QueueEmpty(Q))
Error("Queue underflow");//下溢
p=Q->front; //指向对头结点
x=p->data; //保存对头结点的数据
Q->front=p->next; //将对头结点从链上摘下
if(Q->rear==p)//原队中只有一个结点,删去后队列变空,此时队头指针已为空
Q->rear=NULL;
free(p); //释放被删队头结点
return x; //返回原队头数据
}
(5) 取队头元素
DataType QueueFront(LinkQueue *Q)
{
if(QueueEmpty(Q))
Error("Queue if empty.");
return Q->front->data;
}
注意:
①和链栈类似,无须考虑判队满的运算及上溢。
②在出队算法中,一般只需修改队头指针。但当原队中只有一个结点时,该结点既是队头也是队尾,故删去此结点时亦需修改尾指针,且删去此结点后队列变空。
③以上讨论的是无头结点链队列的基本运算。和单链表类似,为了简化边界条件的处理,在队头结点前也可附加一个头结点,增加头结点的链队列的基本运算【参见练习】
假设数据元素为int型
大概的函数如下所示:
功能函数没怎么写注释,如果你不是很懂的话可以看下书,或者拿只笔出来画画,只是你对这个还没能够明白才不懂的,你把单链表的创建删除过程在纸上一画就会慢慢熟悉明白了的
#include <iostream>
using namespace std;
struct Node
{
int data;
Node *next; //链表节点的结构
};
struct Queue
{
Node *front;
Node *rear;
}; // 队列的首尾指针
int Setnull(Queue &Q)
{
Q.front=Q.rear=new Node; //将队列置空 也是初始化
if(!Q.front)
return 0;
Q.front->next=NULL;
return 1;
}
int empty(Queue Q)
{
if(Q.front==Q.rear)
return 1;
else
return 0;
}
int getfirst(Queue &Q)
{
if(empty(Q))
{
cout<<"the queue is empty!"<<endl;
return 0;
}
else
return Q.front->next->data;
}
int enqueue (Queue &Q)
{
Node *p;
int elem;
cout<<"输入一个要进队列的数"<<endl;
cin>>elem;
p=new Node;
if(!p)
return 0;
p->data=elem;
Q.rear->next=p;
Q.rear=p;
Q.rear->next=NULL;
return 1;
}
int del(Queue &Q)
{
if(empty(Q))
{
cout<<"The queue is empty!"<<endl;
return 0;
}
else
{
Node *p;
p=Q.front->next;
Q.front->next=p->next;
if(Q.rear==p)
Q.rear=Q.front;
delete p;
return 1;
}
return 1;
}
void traverse(Queue Q)
{
Q.front=Q.front->next;
while(Q.front)
{
cout<<Q.front->data<<' ';
Q.front=Q.front->next;
}
cout<<endl;
}
void showTable(Queue Q)
{
system("cls");//清屏的作用
cout<<"======================================"<<endl;
cout<<" 1----入队 "<<endl;
cout<<" 2----出队 "<<endl;
cout<<" 3----将队列置空 "<<endl;
cout<<" 4----队列第一个元素 "<<endl;
cout<<" 5----退出"<<endl;
cout<<"======================================"<<endl;
if(empty(Q))
{
cout<<"目前队列内没有元素,为空,选择1向队列内输入元素"<<endl;
}
else
{
cout<<"当前队列内的元素是:";
traverse(Q);
}
cout<<endl;
cout<<"请给出你的选择:";
}
void main()
{
Queue Q;
Setnull(Q);
bool flag=true;
char ch;
while(flag)
{
showTable(Q);
cin>>ch;
if(ch=='1')
{
enqueue (Q);
}
else if(ch=='2')
{
del(Q);
}
else if (ch=='3')
{
Setnull(Q);
cout<<"队列被置空"<<endl;
}
else if(ch=='4')
{
cout<<"队列的第一个元素是"<<getfirst(Q)<<endl;
}
else if (ch=='5')
{
flag=false;
cout<<"用户选择退出……"<<endl;
}
else
{
cout<<" 输入错误,请重新输入"<<endl;
}
system("pause");
}
}