队列的链式表示和实现:
编写一个程序实现链队列的各种基本运算,并在此基础上设计一个主程序,完成如下功能:
- 初始化并建立链队列
- 销毁链队列
- 入队
- 出队
- 遍历链队列
- 判断链队列是否为空
- 清空链队列
- 获取链队列长度
- 获取链队列头元素
代码(C语言):
/*链队列的实现及常用操作测试*/
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include <time.h>
/*链队列的数据结构*/
typedef int QElemType;
typedef struct QNode //队列节点
{
QElemType data;
struct QNode* next;
} QNode, * QueuePtr;
typedef struct
{
QueuePtr front; //队头指针
QueuePtr rear; //队尾指针
} LinkQueue;
/*函数声明列表*/
int InitQueue(LinkQueue* Q); //1 初始化链队列
int DestroyQueue(LinkQueue* Q); //2 销毁链队列
int EnQueue(LinkQueue* Q, QElemType e); //3 入队
int DeQueue(LinkQueue* Q, QElemType* e); //4 出队
int QueueEmpty(LinkQueue Q); //5 判断链队列是否为空
void ClearQueue(LinkQueue* Q); //6 清空链队列
int QueueLength(LinkQueue Q); //7 获取链队列长度
int GetHead(LinkQueue Q, QElemType* e); //8 获取队头元素
void QueueTraverse(LinkQueue Q); //9 遍历并输出链队列
/*主函数*/
int main(void)
{
int n = 0, k = 0, i = 0;
QElemType d = 0;
LinkQueue Q;
srand((unsigned)time(NULL));
int status = InitQueue(&Q);/*构造一个空队列*/
if (status) printf("队列初始化成功!\n");
else printf("队列初始化失败!\n");
printf("输入队列初始元素个数:");
scanf("%d", &n);
printf("队列初始化成功!\n执行%d次入队操作:\n", n);
for (i = 0; i < n; i++)
{
d = rand() % 90 + 10;
printf("第%-2d次:元素%d入队\n", i + 1, d);
EnQueue(&Q, d); //入队
}
printf("打印当前队列:");
QueueTraverse(Q);
k = QueueLength(Q); //获取队列长度
printf("\n当前队列长度为:%d\n\n", QueueLength(Q));
printf("执行%d次出队操作:\n", k / 2);
for (i = 0; i < k / 2; i++)
{
DeQueue(&Q, &d); //出队
printf("第%-2d次:元素%d出队", i + 1, d);
printf("\t打印当前队列:");
QueueTraverse(Q);
}
n = GetHead(Q, &d); //获取队头元素,保存到d中
if (n) printf("\n队头元素的值:%d\n", d);
printf("执行清空队列操作\n");
ClearQueue(&Q); //清空队列
printf("清空队列后:q.front=%p q.rear=%p q.front->next=%p\n", Q.front, Q.rear, Q.front->next);
DestroyQueue(&Q);
printf("销毁队列后:q.front=%p q.rear=%p\n", Q.front, Q.rear);
return 0;
}
/*函数实现部分*/
/*【功能1 初始化链队列】*/
int InitQueue(LinkQueue* Q)
{
Q->front = Q->rear = (QueuePtr)malloc(sizeof(QNode));
if (!Q->front) return 0;/*生成头节点失败*/
Q->front->next = NULL;
return 1; //初始化成功则返回1
}
/*【功能2 销毁链队列】*/
int DestroyQueue(LinkQueue* Q)
{
while (Q->front)
{
Q->rear = Q->front->next; /*Q->rear指向Q->front的下一个节点*/
free(Q->front);/*释放Q->front所指节点*/
Q->front = Q->rear; /*Q->front指向Q->front的下一个节点*/
}
return 1;
}
/*【功能3 入队】*/
int EnQueue(LinkQueue* Q, QElemType e)
{
QueuePtr p = (QueuePtr)malloc(sizeof(QNode)); /*动态生成新节点*/
if (!p) return 0; //生成失败则返回0
p->data = e; //将e的值赋给新节点
p->next = NULL; //新节点的指针为空
Q->rear->next = p; //原队尾节点的指针域为指向新节点
Q->rear = p; //尾指针指向新节点
return 1; //入队成功则返回1
}
/*【功能4 出队】*/
int DeQueue(LinkQueue* Q, QElemType* e)
{
if (Q->front == Q->rear) return 0; //队列为空则返回0
QueuePtr p = Q->front->next; //p指向队头节点
*e = p->data; //队头元素赋给e
Q->front->next = p->next; //队头节点指向下一个节点
if (Q->rear == p) Q->rear = Q->front; //如果删除的是队尾节点,则修改队尾指针指向头节点
free(p);
return 1; //出队成功则返回1
}
/*【功能5 判断链队列是否为空】*/
int QueueEmpty(LinkQueue Q)
{
if (Q.front->next == NULL) return 1; //如果队列为空则返回1
else return 0;
}
/*【功能6 清空链队列】*/
void ClearQueue(LinkQueue* Q)
{
Q->front->next = NULL;
}
/*【功能7 获取链队列长度】*/
int QueueLength(LinkQueue Q)
{
int i = 0; //计数器清0
QueuePtr p = Q.front; //p指向头节点
while (p != Q.rear) //如果p所指向的不是尾节点
{
i++; //则计数器加1
p = p->next;
}
return i;
}
/*【功能8 获取队头元素】*/
int GetHead(LinkQueue Q, QElemType* e)
{
QueuePtr p;
if (Q.front == Q.rear)
return 0;
p = Q.front->next; //p指向队头节点
*e = p->data; //将队头元素的值赋给e
return 1;
}
/*遍历并输出队列(队头到队尾)*/
void QueueTraverse(LinkQueue Q)
{
QueuePtr p = Q.front->next;
while (p)
{
printf("%d ", p->data);
p = p->next;
}
printf("\n");
}