18.11.25
(基于C语言,欢迎指正)
链队列
队列的链式存储结构,其实就是线性表的单链表,只是它只能尾进头出而已,我们简称它为单链表,和队列的顺序存储结构一样,链队列也需要两个指向队首和队尾的指针front和rear,但是他们的指向稍微有点不同
下文描述中,队头等于队首,但不等于头结点
对于队列的顺序存储结构,front指向队头,rear指向队尾的下一个元素,像这样
(图丑了点-_-||)
对于链队列来说可不一样,front指向的是头结点(头结点不是队首,在队首前面,头结点没有数值),而rear指向队尾
像这样
然后就可以开始写这个程序了
准备工作
- 头文件
- 数据类型设定
- 结点设定
(注意,链队列需要设定两个结构体,一个是结点的类型,一个是队列的结构体指针其中只包含front和rear,要对整个链队列进行一些入队出队或者打印等操作时,都是传入队列的结构体指针,而不是只传一个结点)
#include<stdio.h>
#include<stdlib.h>
typedef int QElemType;//认为int 是QElemType
typedef struct QNode{ //队列结点定义
QElemType data; //包括一个数据域
struct QNode *next; //一个指针域,指向下一个结点
}QNode,*QueuePtr;
typedef struct{ //队列的结构体定义
QueuePtr front,rear;
}LinkQueue;
初始化
一开始的时候,链队列中没有数值,front和rear都指向头结点
void InitQueue(LinkQueue *Q){//初始化
QueuePtr H=(QueuePtr)malloc(sizeof(QNode));//给头结点分配内存
if(!H){
printf("内存分配失败");
exit(1);
}
Q->front=H; //front和rear都指向头结点
Q->rear=H;
}
入队列
将新插入的元素插在队尾后面
void EnQueue(LinkQueue *Q,QElemType e){//入队列,传入头结点指针
QueuePtr S=(QueuePtr)malloc(sizeof(QNode));//给插入的结点分配动态内存
if(!S){
exit(2);
}
S->next=NULL;//新结点的next指向空
S->data=e;
Q->rear->next=S;
Q->rear=S;
}
出队列
首先要判断队列是否已经空了,即front和rear是不是指向头结点,空了就不能再出了
其次,如果将要出队列时,只剩下最后一个元素了,那么就要先将rear指针指向头结点,别搞丢了,在将出队列的结点内存释放掉
void DeQueue(LinkQueue *Q,QElemType *e){//出队列,并用*e存储出去的值
if(Q->front==Q->rear){
exit(3);
}
QueuePtr P;
P=Q->front->next;
*e=P->data;
Q->front->next=P->next;
if(Q->rear==P){ //只剩下最后一个元素了,那么就要先将rear指针指向头结点
Q->rear=Q->front;
}
free(P);
}
打印
需要一个定位指针p,从队头一直走下去
void Print(LinkQueue *Q){//打印函数,队列空不打印
if(Q->front==Q->rear){
printf("链队列已空\n");
exit(3);
}
QueuePtr p;
p=Q->front->next;
while(p){
printf("%d ",p->data);
p=p->next;
}
printf("\n");
}
这样链队列的一些基本操作都写完了,我们在主函数中调试一下
源程序调试
#include<stdio.h>
#include<stdlib.h>
typedef int QElemType;//认为int 是QElemType
typedef struct QNode{ //队列结点定义
QElemType data; //包括一个数据域
struct QNode *next; //一个指针域,指向下一个结点
}QNode,*QueuePtr;
typedef struct{ //队列的结构体定义
QueuePtr front,rear;
}LinkQueue;
void InitQueue(LinkQueue *Q){//初始化
QueuePtr H=(QueuePtr)malloc(sizeof(QNode));//给头结点分配内存
if(!H){
printf("内存分配失败");
exit(1);
}
Q->front=H; //front和rear都指向头结点
Q->rear=H;
}
void EnQueue(LinkQueue *Q,QElemType e){//入队列,传入头结点指针
QueuePtr S=(QueuePtr)malloc(sizeof(QNode));//给插入的结点分配动态内存
if(!S){
exit(2);
}
S->next=NULL;//新结点的next指向空
S->data=e;
Q->rear->next=S;
Q->rear=S;
}
void DeQueue(LinkQueue *Q,QElemType *e){//出队列,并用*e存储出去的值
if(Q->front==Q->rear){
exit(3);
}
QueuePtr P;
P=Q->front->next;
*e=P->data;
Q->front->next=P->next;
if(Q->rear==P){ //只剩下最后一个元素了,那么就要先将rear指针指向头结点
Q->rear=Q->front;
}
free(P);
}
void Print(LinkQueue *Q){//打印函数,队列空不打印
if(Q->front==Q->rear){
printf("链队列已空\n");
exit(3);
}
QueuePtr p;
p=Q->front->next;
while(p){
printf("%d ",p->data);
p=p->next;
}
printf("\n");
}
int main(){
LinkQueue Q;
InitQueue(&Q);
int num,e,i;
for(i=0;i<10;i++){
EnQueue(&Q,i);
}
printf("此时链队列为:");
Print(&Q);
printf("输入要删除的结点的个数:");
scanf("%d",&num);
for(i=0;i<num;i++){
printf("删除第%d个结点,此时链队列为:\n",i+1);
DeQueue(&Q,&e);
Print(&Q);
}
printf("\n最终队列为:\n");
Print(&Q);
}