链式队列的概念
1.1 链式队列的定义
- 链式队列是基于单链表(带头结点)的存储表示实现的队列。
1.2 链式队列中各元素的逻辑及存储关系
- 链式队列可以采用单链表作为其存储表示,因此,可以在链式队列的声明中用单链表定义它的存储空间。
- 链式队列的队头指针指向单链表的第一个结点,队尾指针指向单链表的最后一个结点。
- 注:链式队列的队头元素存放在单链表的第一个结点内,若要从队列中退出一个元素,必须从单链表中删去第一个结点,而存放着新元素的结点应插在队列的队尾,即单链表的最后一个结点后面,这个新节点将成为新的队尾。
1.3 链式队列的特点
- 用单链表表示的链式队列特别适合于数据元素变动比较大的情况,而且不存在队列满而产生溢出的情况。
- 若程序中要使用多个队列,用链接表示不仅能够提高效率,还可以达到共享存储空间的目的。
- 使用链式队列不会出现存储分配不合理的问题,也不需要进行存储的移动。
链式队列的图示
C++语言实现
/*链式队列(Linked Queue)相关操作*/
#include <iostream>
#include <malloc.h>
#include <cstdlib>
using namespace std;
//链式队列结点
typedef struct QNode{
char data; //元素值
struct QNode *next; //指向下一个结点的指针
}QNode, *QueuePtr;
//链式队列结构
typedef struct{
QueuePtr front; //队头指针
QueuePtr rear; //队尾指针
}LinkQueue;
//初始化队列
bool InitQueue(LinkQueue *Q)
{
Q->front = Q->rear = (QueuePtr)malloc(sizeof(QNode)); //为队头指针和队尾指针分配所指向的内存(即为空表头分配内存)
if(!Q->front || !Q->rear) //内存分配失败
exit(0);
Q->front->next = NULL; //空表头指向NULL
return true;
}
//销毁队列
bool DestroyQueue(LinkQueue *Q)
{
while(Q->front != NULL) //从空表头开始沿着链表的顺序依次释放结点
{
Q->rear = Q->front->next;
free(Q->front); //释放队头指针所指结点
Q->front = Q->rear;
}
return true;
}
//清空队列
bool ClearQueue(LinkQueue *Q)
{
QueuePtr p, q;
p = Q->front->next;
Q->front->next = NULL;
Q->rear = Q->front;
while(p != NULL)
{
q = p; //q指向被释放结点
p = p->next;
free(q);
}
return true;
}
//判断队列是否为空
bool QueueEmpty(LinkQueue Q)
{
if(Q.front == Q.rear)
return true;
else
return false;
}
//获取队列长度
int QueueLength(LinkQueue Q)
{
int length = 0;
QueuePtr p = Q.front; //p用于遍历整个队列
while(p != Q.rear)
{
length++;
p = p->next;
}
return length;
}
//获取队列头元素(队列第一个元素)
bool GetHead(LinkQueue Q, char *elem)
{
if(Q.front == Q.rear) //队列为空
{
cout<<"队列为空,获取队头元素失败!"<<endl;
return false;
}
*elem = Q.front->next->data;
return true;
}
//入队
bool EnQueue(LinkQueue *Q, char elem)
{
QueuePtr p = (QueuePtr)malloc(sizeof(QNode));
if(!p) //内存分配失败
exit(0);
p->data = elem;
p->next = NULL;
Q->rear->next = p;
Q->rear = p;
return true;
}
//出队
bool DeQueue(LinkQueue *Q, char *elem)
{
if(Q->front == Q->rear) //队列为空
{
cout<<"队列为空!"<<endl;
return false;
}
QueuePtr q;
q = Q->front->next; //q指向队列的第一个元素
*elem = q->data;
Q->front->next = q->next;
if(q == Q->rear) //队列只有一个元素(即被删除结点是队尾指针指向的结点,删除后队列为空)
{
Q->rear = Q->front;
}
free(q);
return true;
}
//遍历队列
bool TravelQueue(LinkQueue Q)
{
QueuePtr p;
p = Q.front->next;
while(p)
{
cout<<p->data<<" ";
p = p->next;
}
cout<<endl;
return true;
}
int main()
{
char temp;
char e; //元素值
LinkQueue Q; //队列
/*** 初始化队列 ***/
InitQueue(&Q);
cout<<"初始化队列后,队列是否为空? ";
if(QueueEmpty(Q))
cout<<"是"<<endl;
else
cout<<"否"<<endl;
/*** 向队列中插入元素 ***/
cout<<"向队列中插入元素:"<<endl;
while(cin>>temp)
{
EnQueue(&Q, temp); //将元素temp插入队列
if(cin.get() == '\n')
break;
}
cout<<"插入元素后队列的值为:"<<endl;
TravelQueue(Q); //遍历队列
cout<<"队列的长度为:"<<QueueLength(Q)<<endl; //获取队列长度
cout<<"插入元素后,队列是否为空? ";
if(QueueEmpty(Q))
cout<<"是"<<endl;
else
cout<<"否"<<endl;
/*** 删除队列中的3个元素,并打印对应的值 ***/
cout<<"出队3个元素,依次为:";
for (int j=0; j<3; j++)
{
DeQueue(&Q, &e); // 删除队头元素,将值存到e中
cout<<e<<" ";
}
cout<<endl;
cout<<"3个元素出队后,队列的值为:"<<endl;
TravelQueue(Q); //遍历队列
cout<<"队列的长度为:"<<QueueLength(Q)<<endl; //获取队列长度
/*** 获取队列头元素的值 ***/
if(GetHead(Q, &e)) //获取队列头元素
{
cout<<"队列头元素为:"<<e<<endl;
}
/*** 清空队列元素 ***/
ClearQueue(&Q); //清空队列元素
cout<<"清空队列后,队列是否为空? ";
if(QueueEmpty(Q))
cout<<"是"<<endl;
else
cout<<"否"<<endl;
cout<<"队列中的元素为:"<<endl;
TravelQueue(Q); // 遍历元素
if(DestroyQueue(&Q))
cout<<"已销毁队列!"<<endl;
return 0;
}