一、实验目的
1. 掌握队列的链式存储及初始化、创建、求长、销毁、入队、出队等基本操作。
2. 使用C/C++写出链式队列。
3. 了解队列相较于顺序表的特殊性,能在不同情况下选择合适的存储方式。
二、实验要求
1.写出链式队列存储及详细算法步骤;
三、实验过程
实验环境:visual studio 2017
实验步骤:
1. 初始化链队Q,定义函数名为Init_LQueue;
2. 创建链队Q,定义函数名为Create_LQueue;
3. 求链队Q的长度(元素个数),定义函数名为Length_LQueue;
4. 打印链队Q,定义函数名为Print_LQueue;
5. 销毁链队Q,定义函数名为Destory_LQueue;
6. 元素入队,定义函数名为Enqueue;
7. 元素出队,定义函数名为Dequeue;
LQueue.h
#define ELEMTYPE int //定义一个标识符来表示链队数据的类型
#include<stdio.h> //调用头文件
#include<stdlib.h> //调用头文件
typedef struct DataNode //构建结构体变量存储链队数据相关信息
{
ELEMTYPE data; //存放元素
struct DataNode* next; //后继结点指针
}DataNode,*Queue; //DataNode为结构体类型别名,Queue为结构体指针
typedef struct QueueNode //构建结构体变量存储链队结点相关信息
{
DataNode* front; //队头指针
DataNode* rear; //队尾指针
}QueueNode; //结构名为QueueData
void Init_LQueue(Queue* Q,QueueNode* P); //声明初始化函数——Init_LQueue
void Create_LQueue(Queue* Q,QueueNode* P); //声明创建函数——Create_LQueue
int Length_LQueue(Queue Q); //声明求长函数——Length_LQueue
void Print_LQueue(Queue Q); //声明打印函数——Print_LQueue
void Destory_LQueue(Queue* Q,QueueNode* P); //声明销毁函数——Destory_LQueue
void Enqueue(QueueNode*P, ELEMTYPE e); //声明入队函数——Enqueue
void Dequeue(Queue* Q, QueueNode*P, ELEMTYPE* e); //声明出队函数——Dequeue
LQueue.c
#include "LQueue.h" //调用头文件
void Init_LQueue(Queue* Q,QueueNode* P) //初始化链队Q
{
P = (QueueNode*)malloc(sizeof(QueueNode)); //用malloc给P分配一块内存
(*Q) = (Queue)malloc(sizeof(DataNode)); //用malloc给链队Q分配一块内存
P->rear = P->front = (*Q)->next = NULL; //队头指针、队尾指针和头结点的指针域置为空
}
void Create_LQueue(Queue* Q,QueueNode* P) //创建链队Q
{
int length; //定义整型变量length表示链队Q队长
printf("Please input the length:"); //提示输入队长length
scanf("%d", &length); //输入队长length
P->rear = (*Q); //队尾指针指向头结点
for (int n = 1; n <= length; n++) //向链队Q中添加n个数据
{
DataNode* p; //定义结构体指针类型变量p
p = (DataNode*)malloc(sizeof(DataNode)); //用malloc给p分配一块内存
printf("Please input the data:"); //提示输入结点p的数据域
scanf("%d", &p->data); //输入结点p的数据域
p->next = NULL; //此时p为尾结点,所以p的指针域置为空
P->rear->next = p; //原尾结点的指针域指向当前尾结点
P->rear = p; //队尾指针指向当前尾结点p
}
P->front = (*Q)->next; //队头指针指向首元结点
}
int Length_LQueue(Queue Q) //求链队长度
{
DataNode* p = Q; //定义结构体指针类型变量p
int length = 0; //定义整型变量length计数
while (p->next != NULL) //当p的后继结点不为空(即p不是尾结点)时执行循环
{
p = p->next; //p向后挪动,为原来p的后继结点
length++; //计数加1
}
return length; //返回链队长度
}
void Print_LQueue(Queue Q)
{
DataNode* p = Q; //定义结构体指针类型变量p
printf("This Queue is:"); //提示打印队列
while (p->next != NULL) //当p的后继结点不为空(即p不是尾结点)时执行循环
{
p = p->next; //p向后挪动,为原来p的后继结点
printf("%d ", p->data); //打印p的数据域
}
printf("\n"); //换行
}
void Destory_LQueue(Queue* Q, QueueNode* P)
{
DataNode* p = (*Q),*q; //定义结构体指针类型变量p,q
while (p->next != NULL) //当p的后继结点不为空(即p不是尾结点)时执行循环
{
q = p; //q存储当前结点p
p = p->next; //p向后挪动,为原来p的后继结点
free(q); //释放原来结点p的空间
q = NULL; //原来结点p置为空(防止出现悬空指针)
}
free(Q); //释放链队Q的空间
free(P); //释放P的空间
Q = NULL; //Q置为空
P = NULL; //P置为空
}
void Enqueue(QueueNode* P, ELEMTYPE e) //将元素e入队
{
DataNode* p; //定义结构体指针类型变量p
p = (DataNode*)malloc(sizeof(DataNode)); //用malloc给p分配一块内存
p->data = e; //将元素e赋值给p的数据域
p->next = NULL; //p为尾结点,所以指针域为空
P->rear->next = p; //将p链接入队列
P->rear = p; //更新尾结点
}
void Dequeue(Queue* Q, QueueNode*P, ELEMTYPE* e) //将首元结点出队
{
if (Length_LQueue(*Q) == 0) //判断队列为空
{
printf("Dequeue falied.\n"); //提示出队失败
return; //退出函数
}
else //队列不为空
{
*e = P->front->data; //取出原首元结点数据域
(*Q)->next = P->front->next; //更新首元结点
P->front = (*Q)->next; //更新队头指针
}
}
Test_Init_Create_Print.c
#include "LQueue.h" //调用头文件
int main(void) //main()函数
{
Queue Q; //定义结构体指针变量Q
QueueNode P; //定义结构体变量P
Init_LQueue(&Q, &P); //调用Init_LQueue函数将链队Q初始化
Create_LQueue(&Q, &P); //调用Create_LQueue函数创建链队Q
Print_LQueue(Q); //调用Print_LQueue函数打印链队Q
return 0; //返回值
}
Test_Length.c
#include "LQueue.h" //调用头文件
int main(void) //main()函数
{
Queue Q; //定义结构体指针变量Q
QueueNode P; //定义结构体变量P
Init_LQueue(&Q, &P); //调用Init_LQueue函数将链队Q初始化
Create_LQueue(&Q, &P); //调用Create_LQueue函数创建链队Q
printf("This queue's length is:%d\n",Length_LQueue(Q)); //调用Length_LQueue函数打印链队Q长度
return 0; //返回值
}
Test_Enqueue.c
#include "LQueue.h" //调用头文件
int main(void) //main()函数
{
Queue Q; //定义结构体指针变量Q
QueueNode P; //定义结构体变量P
Init_LQueue(&Q, &P); //调用Init_LQueue函数将链队Q初始化
Create_LQueue(&Q, &P); //调用Create_LQueue函数创建链队Q
Print_LQueue(Q); //调用Print_Lqueue函数打印链队Q
ELEMTYPE e; //定义待入队元素e
printf("The element to be enqueue is:"); //提示输入待入队的元素
scanf("%d", &e); //输入待入队的元素
Enqueue(&P,e); //调用Enqueue函数将元素e入队
Print_LQueue(Q); //调用Print_LQueue函数打印链队Q
return 0; //返回值
}
Test_Dequeue.c
#include "LQueue.h" //调用头文件
int main(void) //main()函数
{
Queue Q; //定义结构体指针变量Q
QueueNode P; //定义结构体变量P
Init_LQueue(&Q, &P); //调用Init_LQueue函数将链队Q初始化
Create_LQueue(&Q, &P); //调用Create_LQueue函数创建链队Q
Print_LQueue(Q); //调用Print_LQueue函数打印链队Q
ELEMTYPE e = 0; //定义待入队元素e
Dequeue(&Q, &P, &e); //调用Enqueue函数将元素e入队
Print_LQueue(Q); //调用Print_LQueue函数打印链队Q
return 0; //返回值
}
四、实验结果及分析
测试函数 | 测试用例 | 运行结果 |
Init_LQueue Creat_LQueue Print_LQueue | 5 1,2,3,4,5 | Please input the length:5 Please input the data:1 Please input the data:2 Please input the data:3 Please input the data:4 Please input the data:5 This queue is:1 2 3 4 5 |
0 | Please input the length:0 This queue is: | |
Length_LQueue | 5 1,2,3,4,5 | This queue's length is:5 |
0 | This queue's length is:0 | |
Enqueue | 5 1,2,3,4,5 6 | The element to be enqueue is:6 This Queue is:1 2 3 4 5 6 |
Dequeue | 5 1,2,3,4,5 | This Queue is:2 3 4 5 |
0 | Dequeue falied. This Queue is: |