数据结构总目录
(一)链队图文解析
链队是指采用链式存储结构实现的队列,队列结点与单链表一样,但一个链队需要两个分别指示队头和队尾的头指针和尾指针,用于队列的入队和出队操作。
注意队头不是头结点!!
(二)链队代码解析
1. 基本操作
1.1 存储结构
typedef char DataType;
// 链队的结点结构
typedef struct QNode
{
DataType data; // 结点数据域
struct QNode *next; // 结点指针域
}QNode;
// 链队的头尾指针
typedef struct
{
QNode *rear; // 链队尾指针
QNode *front; // 链队头指针
}LinkQueue;
1.2 初始化
// 初始化
void InitQueue(LinkQueue **LQ)
{
// 链队的头指针和尾指针都指向头结点(为头结点分配空间)
(*LQ)->front = (*LQ)->rear = (QNode *)malloc(sizeof(QNode));
(*LQ)->front->next = NULL;
printf("队列已初始化!\n");
}
1.3 入队
// 入队(链表尾插)
void EnQueue(LinkQueue *LQ)
{
DataType x;
fflush(stdin);
printf("请输入入队数据:");
scanf("%c", &x);
// 创建新结点
QNode *s = (QNode *)malloc(sizeof(QNode));
s->data = x;
s->next = NULL;
// 尾节点后连接新结点s
LQ->rear->next = s;
// 链队的尾指针指向新结点s
LQ->rear = s;
printf("入队:%c\n", LQ->rear->data);
}
1.4 出队
// 出队(链表头删)
void DeQueue(LinkQueue *LQ)
{
if (LQ->front == LQ->rear)
{
printf("队列为空!\n");
}
else
{
// 获取队头结点(头结点指向的第一个结点)
QNode *p = LQ->front->next;
// 头结点指向第二个结点
LQ->front->next = p->next;
// 删除最后一个结点时,链队尾指针需要指向头指针
if (p == LQ->rear)
{
LQ->rear = LQ->front;
}
printf("出队:%c\n", p->data);
// 销毁结点
free(p);
}
}
2. 源代码及测试
2.1 源代码:
#include<stdio.h>
#include<stdlib.h>
typedef char DataType;
// 链队的结点结构
typedef struct QNode
{
DataType data; // 结点数据域
struct QNode *next; // 结点指针域
}QNode;
// 链队的头尾指针
typedef struct
{
QNode *rear; // 链队尾指针
QNode *front; // 链队头指针
}LinkQueue;
// 初始化
void InitQueue(LinkQueue **LQ)
{
// 链队的头指针和尾指针都指向头结点(为头结点分配空间)
(*LQ)->front = (*LQ)->rear = (QNode *)malloc(sizeof(QNode));
(*LQ)->front->next = NULL;
printf("队列已初始化!\n");
}
// 入队(链表尾插)
void EnQueue(LinkQueue *LQ)
{
DataType x;
fflush(stdin);
printf("请输入入队数据:");
scanf("%c", &x);
// 创建新结点
QNode *s = (QNode *)malloc(sizeof(QNode));
s->data = x;
s->next = NULL;
// 尾节点后连接新结点s
LQ->rear->next = s;
// 链队的尾指针指向新结点s
LQ->rear = s;
printf("入队:%c\n", LQ->rear->data);
}
// 出队(链表头删)
void DeQueue(LinkQueue *LQ)
{
if (LQ->front == LQ->rear)
{
printf("队列为空!\n");
}
else
{
// 获取队头结点(头结点指向的第一个结点)
QNode *p = LQ->front->next;
// 头结点指向第二个结点
LQ->front->next = p->next;
// 删除最后一个结点时,链队尾指针需要指向头指针
if (p == LQ->rear)
{
LQ->rear = LQ->front;
}
printf("出队:%c\n", p->data);
// 销毁结点
free(p);
}
}
// 遍历队列序列
void Display(LinkQueue *LQ)
{
QNode *p = LQ->front;
printf("队列: 队头[ ");
while (p != LQ->rear)
{
p = p->next;
printf("%c ", p->data);
}
printf("]队尾\n");
}
// 取队头元素
void GetQueueHead(LinkQueue *LQ)
{
if (LQ->front == LQ->rear)
{
printf("队列为空!\n");
}
else
{
QNode *p = LQ->front->next;
printf("队头:%c\n", p->data);
}
}
// 取队尾元素
void GetQueueTail(LinkQueue *LQ)
{
if (LQ->front == LQ->rear)
{
printf("队列为空!\n");
}
else
{
QNode *p = LQ->rear;
printf("队尾:%c\n", p->data);
}
}
// 求队列长度
void GetLength(LinkQueue *LQ)
{
int len;
QNode *p = LQ->front;
while (p != LQ->rear)
{
p = p->next;
len++;
}
printf("队列长度 = %d\n", len);
}
int main()
{
printf("***********************************\n");
printf("0:退出\t1:入队\t2:出队\t3:遍历\n");
printf("4:队头\t5:队尾\t6:求队列长度\n");
printf("***********************************\n");
int k;
LinkQueue *LQ;
InitQueue(&LQ);
while (1)
{
printf("请输入操作序号:");
scanf("%d", &k);
if (!k)
{
break;
}
switch (k)
{
case 1: EnQueue(LQ); break;
case 2: DeQueue(LQ); break;
case 3: Display(LQ); break;
case 4: GetQueueHead(LQ); break;
case 5: GetQueueTail(LQ); break;
case 6: GetLength(LQ); break;
default:break;
}
printf("\n");
}
system("pause");
return 0;
}