队列的链式存储——链队列
话说链栈有一个栈顶指针;而队列和栈是有差别的,队列只能一头进另一头出,而链队列的进出口都有警卫把守,分别是队头指针(front)大哥和队尾指针(rear)小弟,有的剧情会是这样:大哥躺在椅子上小弟帮大哥办事,那么这头指针大哥就是在队的头部始终不动,稳如狗,而尾指针小弟就随着队列有元素入队,尾指针就要往右移动。小弟都是这样,再累也不怕。
来看一看大哥和小弟的生活图
言归正传,链队列的结构体定义,和链栈很相似,链队列定义了要移动的队尾指针和不动的队头指针;链表的头节点作为链队列的空队。
typedef struct QNode
{
ElemType data;
struct QNode *next;
}QNode, *QueueN;
typedef struct
{
QueueN Front; //This queue head pointer
QueueN Rear; //This queue tail pointer
}LinkQueue;
关于链队列的入队和出队看下图
代码部分
#include <stdio.h>
#include <stdlib.h>
typedef char ElemType;
typedef struct QNode
{
ElemType data;
struct QNode *next;
}QNode, *QueueN;
typedef struct
{
QueueN Front; //This queue head pointer
QueueN Rear; //This queue tail pointer
}LinkQueue;
void init_Queue(LinkQueue *Q)
{
Q->Front = (QueueN)malloc(sizeof(QNode));
if (!Q->Front)
{
printf("The memory allocation failed !\n");
return;
}
Q->Rear = Q->Front;
Q->Front->next = NULL;
}
void print_Queue(LinkQueue Q)
{
if (Q.Front == Q.Rear)
{
printf("The queue is empty!\n");
return;
}
Q.Front = Q.Front->next;
while(Q.Front)
{
printf(" %c ", Q.Front->data);
Q.Front = Q.Front->next;
}
printf("\n");
}
void EnQueue(LinkQueue *Q, ElemType e)
{
QueueN qNew = (QueueN)malloc(sizeof(QNode));
if (!qNew)
{
printf("The memory allocation failed !\n");
return;
}
qNew->data = e;
qNew->next = NULL;
Q->Rear->next = qNew;
Q->Rear = qNew;
}
bool DeQueue(LinkQueue *Q, ElemType *e)
{
QueueN p;
if (Q->Front == Q->Rear)
{
printf("The queue is empty!\n");
return false;
}
p = Q->Front->next;
*e = p->data;
Q->Front->next = p->next;
if (Q->Rear == p)
{
Q->Rear = Q->Front;
}
free(p);
return true;
}
int length_Queue(LinkQueue Q)
{
int len = 0;
if (Q.Front == Q.Rear)
{
printf("The queue is empty! ");
return len;
}
else
{
Q.Front = Q.Front->next;
while(Q.Front)
{
++len;
Q.Front = Q.Front->next;
}
return len;
}
}
bool clear_Queue(LinkQueue *Q)
{
if (Q->Front == Q->Rear)
{
return true;
}
QueueN q;
QueueN p;
q = Q->Front->next;
while(q)
{
p = q->next;
free(q);
q = p;
}
Q->Front->next = NULL;
Q->Rear = Q->Front;
return true;
}
bool destroy_Queue(LinkQueue *Q)
{
clear_Queue(Q);
free(Q->Front);
Q->Front = NULL;
Q->Rear = NULL;
Q = NULL;
return true;
}
int main()
{
LinkQueue Q;
init_Queue(&Q); //Initialization queue
int option = 1;
ElemType e;
int len = 0;
printf("\n 1. Initialization queue\n 2. Traverse queue\n 3. Enqueue\n 4. Dequeue\n 5. Queue`s length\n 6. Clear queue\n 7. Destroy queue\n 0. Exit\n");
while(option)
{
printf("Please operate on the queue: ");
scanf("%d", &option);
switch(option)
{
case 1:
init_Queue(&Q);
break;
case 2:
//Print the queue of all elements
print_Queue(Q);
break;
case 3:
getchar();
printf("Please enter the element to be enqueued: ");
scanf("%c", &e);
//Enqueue opertion of the queue
EnQueue(&Q, e);
break;
case 4:
getchar();
//Dequeue opertion of the queue
if (DeQueue(&Q, &e))
{
printf("The element to be dequeued is %c\n", e);
}
else
{
printf("Dequeue is fail !\n");
}
break;
case 5:
//Calculate the length of the queue
len = length_Queue(Q);
printf("The queue`s length is %d\n", len);
break;
case 6:
//Clear the queue
if (clear_Queue(&Q))
{
printf("The queue has been cleared!\n");
}
break;
case 7:
//Destroy the queue
if (destroy_Queue(&Q))
{
printf("The queue has been destroy!\n");
}
break;
case 0:
exit(0);
default:
printf("Incorrect operation! Please re-operate!\n");
break;
}
scanf("%*[^\n]%*c");
option = 9;
}
return 0;
}