队列的链式存储实现
链式队列 : 用链表形式实现的队列。链表结点为队列数据存储区,链表结点包括两部分数据存储
区和指针存储区。
数据存储区 :存放真实有效数据的区域。
指针存储区 :存放下一个链表结点的地址。
二、实现过程
1.链式队列概念图(有头结点):
2.链式队列结构体:
头指针执行头结点,尾指针指向尾结点
//线性表存储结构
typedef struct LNode
{
ElemType data; //存储队列中的元素。
struct LNode* next; //next指针
}LNode;
//队列的指针头和尾
typedef struct
{
LNode *front,*rear; // 队列的头指针和尾指针。
}LinkQueue,*PLinkQueue;
3.队列的基本操作
4.代码实现:
/*
程序名:linkqueue.cpp 此程序演示队列的链表实现(带头结点)。
*/
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
typedef int ElemType; //自定义队列的数据元素为整数。
//线性表存储结构
typedef struct LNode
{
ElemType data; //存储队列中的元素。
struct LNode* next; //next指针
}LNode;
//队列的指针头和尾
typedef struct
{
LNode *front,*rear; // 队列的头指针和尾指针。
}LinkQueue,*PLinkQueue;
//队列QQ的初始化操作。
int InitQueue(PLinkQueue QQ);
// 销毁队列QQ。
void DestroyQueue(PLinkQueue QQ);
// 清空队列。
void Clear(PLinkQueue QQ);
// 元素入队,返回值:0-失败;1-成功。
int InQueue(PLinkQueue QQ, ElemType *ee);
// 打印队列中全部的元素。
void PrintQueue(PLinkQueue QQ);
// 求队列的长度,返回值:>=0-队列QQ元素的个数。
int Length(PLinkQueue QQ);
// 判断队列是否已满,链式队列不存在队满的说法。
int IsFull(PLinkQueue QQ);
// 判断队列是否为空,返回值:1-空,0-非空或失败。
int IsEmpty(PLinkQueue QQ);
// 元素出队,返回值:0-失败;1-成功。
int OutQueue(PLinkQueue QQ, ElemType *ee);
// 获取队头元素,返回值:0-失败;1-成功。
// 只查看队头元素的值,元素不出队。
int GetHead(PLinkQueue QQ, ElemType *ee);
int main()
{
LinkQueue QQ; // 创建队列。
memset(&QQ,0,sizeof(LinkQueue));
InitQueue(&QQ); // 初始化队列。
ElemType ee; // 创建一个数据元素。
printf("元素(1、2、3、4、5、6、7、8、9、10)入队。\n");
ee=1; InQueue(&QQ, &ee);
ee=2; InQueue(&QQ, &ee);
ee=3; InQueue(&QQ, &ee);
ee=4; InQueue(&QQ, &ee);
ee=5; InQueue(&QQ, &ee);
ee=6; InQueue(&QQ, &ee);
ee=7; InQueue(&QQ, &ee);
ee=8; InQueue(&QQ, &ee);
ee=9; InQueue(&QQ, &ee);
ee=10; InQueue(&QQ, &ee);
printf("队列的长度是%d\n",Length(&QQ));
printf("打印队列元素:\n");
PrintQueue(&QQ);
if (OutQueue(&QQ,&ee)==1) printf("出队的元素值为%d\n",ee);
if (OutQueue(&QQ,&ee)==1) printf("出队的元素值为%d\n",ee);
if (OutQueue(&QQ,&ee)==1) printf("出队的元素值为%d\n",ee);
if (OutQueue(&QQ,&ee)==1) printf("出队的元素值为%d\n",ee);
if (OutQueue(&QQ,&ee)==1) printf("出队的元素值为%d\n",ee);
if (OutQueue(&QQ,&ee)==1) printf("出队的元素值为%d\n",ee);
if (OutQueue(&QQ,&ee)==1) printf("出队的元素值为%d\n",ee);
printf("队列的长度是%d\n",Length(&QQ));
PrintQueue(&QQ);
printf("元素(11、12、13、14、15)入队。\n");
ee=11; InQueue(&QQ, &ee);
ee=12; InQueue(&QQ, &ee);
ee=13; InQueue(&QQ, &ee);
ee=14; InQueue(&QQ, &ee);
ee=15; InQueue(&QQ, &ee);
printf("队列的长度是%d\n",Length(&QQ));
PrintQueue(&QQ);
// 只查看队头元素的值,元素不出队。
if (GetHead(&QQ,&ee)==1) printf("队头的元素值为%d\n",ee);
// printf("清除前front=%p,rear=%p\n",QQ.front,QQ.rear);
Clear(&QQ); // 销毁队列QQ。
// printf("清除后front=%p,rear=%p\n",QQ.front,QQ.rear);
// printf("销毁前front=%p,rear=%p\n",QQ.front,QQ.rear);
DestroyQueue(&QQ); // 销毁队列QQ。
// printf("销毁后front=%p,rear=%p\n",QQ.front,QQ.rear);
return 0;
}
//队列QQ的初始化操作。
int InitQueue(PLinkQueue QQ)
{
if(QQ == NULL){ printf("队列不存在\n"); return 0; }
//创建头结点
LNode* head=(LNode*)malloc(sizeof(LNode));
if(head==NULL){ printf("内存不足,分配结点失败。\n");return 0; }
head->next=NULL;
QQ->front=QQ->rear=head;
return 1;
}
// 销毁队列QQ。删除所有结点
void DestroyQueue(PLinkQueue QQ)
{
//队列指针不存在
if(QQ==NULL){ printf("队列不存在\n"); return ; }
// 未初始化 即头尾指针没有指向头结点
if(QQ->front==NULL){
printf("队列未初始化。\n");
return ;
}
LNode* tmp=QQ->front;
//逐个结点删除
while(tmp != QQ->rear->next)
{
tmp=tmp->next; //下个结点地址
free(QQ->front); //释放本结点地址
QQ->front=tmp; //指针指向下一个结点
}
QQ->front=QQ->rear=NULL;
return ;
}
// 清空队列。删除了除头结点以外的所有结点
void Clear(PLinkQueue QQ)
{
//队列指针不存在
if(QQ==NULL){ printf("队列不存在\n"); return ; }
// 未初始化 即头尾指针没有指向头结点
if(QQ->front==NULL){
printf("队列未初始化。\n");
return ;
}
LNode *head=QQ->front; //保存头结点
LNode* tmp=QQ->front->next; //从首节点开始删除
//逐个结点删除
while(tmp != QQ->rear->next)
{
tmp=tmp->next; //下个结点地址
free(QQ->front); //释放本结点地址
QQ->front=tmp; //指针指向下一个结点
}
QQ->front=QQ->rear=head;
QQ->front->next=QQ->rear->next=NULL;
}
// 元素入队,返回值:0-失败;1-成功。
int InQueue(PLinkQueue QQ, ElemType *ee)
{
//队列指针不存在
if(QQ==NULL){ printf("队列不存在\n"); return 0; }
//未初始化 即头尾指针没有指向头结点
if(QQ->front==NULL){
printf("队列未初始化。\n");
return 0;
}
//新建一个结点
LNode *newnode=(LNode*)malloc(sizeof(LNode));
if(newnode==NULL)return 0;
//将元素值赋值给新结点
memcpy(&newnode->data,ee,sizeof(ElemType));
newnode->next=NULL;
QQ->rear->next=newnode;
QQ->rear=newnode;
return 1;
}
// 打印队列中全部的元素。
void PrintQueue(PLinkQueue QQ)
{
//队列指针不存在
if(QQ==NULL){ printf("队列不存在\n"); return ; }
//未初始化 即头尾指针没有指向头结点
if(QQ->front==NULL){
printf("队列未初始化。\n");
return ;
}
LNode* tmp=QQ->front->next; //从首节点开始输出
//当指针没查询到尾指针的next域,一直查询
while(tmp!=QQ->rear->next){
printf("%3d ",tmp->data);
tmp=tmp->next;
}
printf("\n");
}
// 求队列的长度,返回值:>=0-队列QQ元素的个数。
int Length(PLinkQueue QQ)
{
//队列指针不存在
if(QQ==NULL){ printf("队列不存在\n"); return 0; }
//未初始化 即头尾指针没有指向头结点
if(QQ->front==NULL){
printf("队列未初始化。\n");
return 0;
}
LNode* tmp=QQ->front->next; //从首节点开始计数
if(tmp==NULL)return 0;
int length=1; //头结点序号为1
while(tmp!=QQ->rear)
{
length++;
tmp=tmp->next;
}
return length;
}
// 判断队列是否已满,链式队列不存在队满的说法。
int IsFull(PLinkQueue QQ)
{
//队列指针不存在
if(QQ==NULL){ printf("队列不存在\n"); return 0; }
return 1;
}
// 判断队列是否为空,返回值:1-空,0-非空或失败。
int IsEmpty(PLinkQueue QQ)
{
//队列指针不存在
if(QQ==NULL){ printf("队列不存在\n"); return 0; }
//首尾相等为空
if(QQ->front==QQ->rear)return 1;
return 0;
}
// 元素出队,返回值:0-失败;1-成功。
int OutQueue(PLinkQueue QQ, ElemType *ee)
{
//队列指针不存在
if(QQ==NULL){ printf("队列不存在\n"); return 0; }
if(QQ->front==NULL){printf("队列未初始化");return 0;}
if(IsEmpty(QQ)){ printf("队空,无元素可以出队。\n"); return 0; }
//队头元素出队
LNode* tmp=QQ->front->next;
//队尾
memcpy(ee,&tmp->data,sizeof(ElemType));
QQ->front->next=tmp->next;
// 如果出队的是最后一个结点。
if (QQ->rear==tmp) QQ->rear=QQ->front;
free(tmp);
return 1;
}
// 获取队头元素,返回值:0-失败;1-成功。
// 只查看队头元素的值,元素不出队。
int GetHead(PLinkQueue QQ, ElemType *ee)
{
if(QQ==NULL){ printf("队列不存在\n"); return 0; }
if(QQ->front==NULL){printf("队列未初始化");return 0;}
if(IsEmpty(QQ)){ printf("队空,无元素可以出队。\n"); return 0; }
//取队头元素
memcpy(ee,&QQ->front->next->data,sizeof(ElemType));
return 1;
}