代码参照了严蔚敏、吴伟民编写的数据结构(C语言版)。
所有代码采用C语言编写。讲解请查看注释。
- 注1:书中很多函数采用了引用传值,如InitQueue(LinkQueue &Q)。但C语言并不支持引用传值,因此统一改为地址传值,即InitQueue(LinkQueue *Q)。
头文件及宏定义
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#define OK 1
#define False 0
#define True 1
#define Error 0
typedef定义数据类型和结构体
typedef int QElemType;
typedef int Status;
typedef struct QNode{
QElemType data;
struct QNode *next;
}QNode,* QueuePtr;
typedef struct{
QueuePtr front;//队头指针
QueuePtr rear;//队尾指针
}LinkQueue;
InitQueue(创建)
Status InitQueue(LinkQueue *Q){
Q->front=Q->rear=(QueuePtr)malloc(sizeof(QNode));//为头节点分配内存,剩下的节点创建时再进行分配。队头指针和队尾指针指向头节点
if(!Q->front)
exit(OVERFLOW);
Q->front->next=NULL;
return OK;
}
DestroyQueue(销毁)
Status DestroyQueue(LinkQueue *Q){
while(Q->front){//从头节点开始向后删除
Q->rear=Q->front->next;
Q->front->data=0;
free(Q->front);
Q->front=Q->rear;
}
return OK;
}
ClearQueue(清空)
Status ClearQueue(LinkQueue *Q){
QueuePtr temp=Q->front;//保存头节点
Q->front=Q->front->next;//获得第队头
while(Q->front){//从队头向后删除
Q->rear=Q->front->next;
Q->front->data=0;
free(Q->front);
Q->front=Q->rear;
}
Q->front=temp;//使队头指针指向头节点
Q->rear=temp;//使队尾指针指向头节点
return OK;
}
QueueEmpty(判断队列是否为空)
Status QueueEmpty(LinkQueue Q){
if(Q.front==Q.rear)
return True;
else
return False;
}
QueueLength(获得队列的长度)
int QueueLength(LinkQueue Q){
int length=0;
while(Q.front!=Q.rear){
Q.front=Q.front->next;
length++;
}
return length;
}
GetHead(获得队头元素)
Status GetHead(LinkQueue Q,QElemType *e){//若队列不空,用e返回队头元素
if(Q.front==Q.rear)
return Error;
*e=Q.front->next->data;
return OK;
}
EnQueue( 队尾插入)
Status EnQueue(LinkQueue *Q,QElemType e){//插入元素e为新的队尾元素
QueuePtr p=(QueuePtr)malloc(sizeof(QNode));//为插入的新节点申请内存,使p指向新节点
if(!p)
exit(OVERFLOW);//内存分配失败
p->data=*e;
p->next=NULL;//将插入到队尾
Q->rear->next=p;//插入
Q->rear=p;//更改队尾指针,使其指向这个元素
return OK;
}
DeQueue(队头删除)
Status DeQueue(LinkQueue *Q,QElemType *e){//从队头删除一个元素,用e返回
if(Q->front==Q->rear)//空队的话无法删除
return Error;
QueuePtr p;
p=Q->front->next;//p指向队头元素
*e=p->data;
p->data=0;
Q->front->next=Q->front->next->next;//p指向的队头元素将被删除,所以原队头指针指向下一个元素
if(Q->front->next==Q->rear)//如果只有一个队内元素的话(除去头节点),删除后为空队
Q->rear=Q->front;
free(p);
return OK;
}
QueueTraverse(遍历)
首先需要实现Visit()
Status visit(LinkQueue Q){
while(Q.front!=Q.rear){
printf("%d\n",Q.front->next->data);
Q.front=Q.front->next;
}
return OK;
}
Status QueueTraverse(LinkQueue Q,Status visit()){
visit(Q);
return OK;
}
输入样例
很多函数被我注释掉了,需要使用的话自行取消注释。
int main(void){
LinkQueue Q;
InitQueue(&Q);
int elem1=1,elem2=2,elem3=3;
EnQueue(&Q,elem1);
EnQueue(&Q,elem2);
EnQueue(&Q,elem3);//向队列中插入三个数值
//ClearQueue(&Q);
//QueueEmpty(Q);
//int elem4=0,elem5=0;
//DeQueue(&Q,&elem4);//删除了队头元素1并存储在elem4中
//GetHead(Q,&elem5);//获取新的队头元素2并存储在elem5中
//QueueLength(Q);
QueueTraverse(Q,visit);
DestroyQueue(&Q);
}