鏈佇列的綜合操作(詳解、演示)C語言實現
阿新 • • 發佈:2019-02-09
佇列的簡介
和棧相反,佇列(queue)是一種先進先出(簡稱FIFO)的線性表。它只允許在表的一端進行插入,而在另一端刪除元素。
舉個我們生活中最最常見的例子:銀行排隊(不管什麼排隊),當我們去銀行辦理業務的時候,我們要按照先來後到的規矩,先來的人先處理後面的人候著,先來的人處理完了之後先走…..
根據上面的例子大家應該可以很清楚的理解佇列是什麼了,再來看個示意圖
和線性表類似,佇列也有兩種儲存表示
用連結串列表示的佇列稱為鏈佇列、還有一個迴圈佇列在下一篇部落格講。一個鏈佇列顯然需要兩個分別指向隊頭和隊尾的指標(分別稱為頭指標和尾指標)才能唯一確定。這裡,和線性表的單鏈表一樣,為了操作方便起見,我們也給鏈佇列新增一個頭結點,並令頭結點指標指向頭結點,由此。空的鏈佇列的判決條件為頭指標和尾指標均指向頭結點。
鏈佇列的操作即是單鏈表的插入和刪除操作的特殊情況。只需修改頭尾指標即可,下面的程式實現和演示了,佇列的構造、銷燬、清空佇列、銷燬佇列、判斷佇列是否為空、獲得佇列長度、獲得隊頭、入佇列、出佇列、顯示佇列等功能。
/*********************************************************
- Copyright (C): 2016
- File name : queue.c
- Author : - Zhaoxinan -
- Date : 2016年04月21日 星期四 15時34分59秒
- Description : 單鏈佇列的儲存
* *******************************************************/
#include <stdio.h>
#include <stdlib.h>
#define TRUE 1
#define FALSE -1
#define OK 1
#define ERROR -1
#define OVERFLOW -2
/* ---- 單鏈佇列----佇列的鏈式儲存結構 ---- */
typedef struct Qnode
{
int date;
struct Qnode *next;
}QNode,* QueuePtr;
typedef struct
{
QueuePtr head; //隊頭指標
QueuePtr tail; //隊尾指標
}LinkQueue;
/* ---- 基本操作函式 ---- */
/* ---- 構造一個空佇列 ---- */
int InitQueue(LinkQueue *Q)
{
Q->head = Q->tail = (QueuePtr)malloc(sizeof(QNode));
if (Q->head == NULL)
{
exit(OVERFLOW);
}
Q->tail->next = NULL;
return OK;
}
/* ---- 銷燬佇列Q,Q不再存在 ---- */
int DestoryQueue(LinkQueue *Q)
{
//head->node1->node2->node3->tail;
// tail
// head->node2
while(Q->head)
{
Q->tail = Q->head->next;
free(Q->head);
Q->head = Q->tail;
}
Q->head = Q->tail = NULL;
return OK;
}
/* ---- 將Q清空空佇列 ---- */
int ClearQueue(LinkQueue *Q)
{
QueuePtr temp;
Q->tail = Q->head->next;
while(Q->tail)
{
temp = Q->tail->next; //指向下一個待釋放的單元
free(Q->tail);
Q->tail = temp;
}
Q->tail = Q->head; //修改隊尾指標
return OK;
}
/* ---- 若佇列Q為空佇列,返回TRUE,否則返回FALSE ---- */
int QueueEmpty(LinkQueue Q)
{
if (Q.head == Q.tail && Q.head != NULL)
{
return TRUE;
}
else
{
return FALSE;
}
}
/* ---- 返回Q的元素個數,即佇列的長度 ---- */
int QueueLength(LinkQueue Q)
{
if (Q.head == NULL)
{
return 0;
}
QueuePtr temp;
int count = 0;
temp = Q.head->next;
while(temp != NULL)
{
temp = temp->next;
++count;
}
return count;
}
/* ---- 顯示當前佇列的值從隊頭到隊尾 ---- */
void show_queue(LinkQueue Q)
{
QueuePtr temp;
temp = Q.head->next;
printf(" 當前佇列從頭到尾:");
while(temp != NULL)
{
printf("%d ", temp->date);
temp = temp->next;
}
printf("\n");
}
/* ---- 若佇列不空,則用e返回Q的隊頭元素,並返回OK, 否則返回ERROR ---- */
int GetHead(LinkQueue Q, int *e)
{
if (QueueEmpty(Q) == TRUE)
{
return ERROR;
}
*e = Q.head->next->date;
return OK;
}
/* ---- 插入元素e為Q的新的對尾元素 ---- */
int EnQueue(LinkQueue *Q, int e)
{
if (Q->head == NULL || Q->tail == NULL)
{
return ERROR;
}
QueuePtr ptr = (QueuePtr)malloc(sizeof(QNode));
if (!ptr)
{
exit(OVERFLOW);
}
ptr->date = e;
ptr->next = NULL;
Q->tail->next = ptr;
Q->tail = ptr;
return OK;
}
/* ---- 若佇列不空,則刪除Q的隊頭元素,並用e返回其值,並返回OK,否則返回ERROR ---- */
int DeQueue(LinkQueue *Q, int *e)
{
if (Q->head == Q->tail)
{
return ERROR;
}
/* ptr為臨時變數 */
QueuePtr ptr = (QueuePtr)malloc(sizeof(QNode));
//head->node1->node2->tail;
// ptr
// head->node2->tail
ptr = Q->head->next;
*e = ptr->date;
Q->head->next = ptr->next;
if (Q->tail == ptr)
{
Q->head = Q->tail;
}
free(ptr);
return OK;
}
int main()
{
int i; //迴圈變數
int count; //計數變數
int outque; //出隊元素值
LinkQueue Q;
/* 初始化佇列 */
InitQueue(&Q);
/* 插入10個元素 */
printf("________________入隊10個元素________________\n\n");
for (i = 0; i < 10; i++)
{
/* 入隊 */
EnQueue(&Q, i);
/* 獲得當前佇列中元素個數 */
count = QueueLength(Q);
printf("%2d 入隊_當前佇列中元素個數:%2d",i, count);
show_queue(Q);
}
printf("________________出隊5個元素________________\n\n");
for (i = 0; i < 5; i++)
{
/* 出隊 */
DeQueue(&Q, &outque);
/* 獲得當前佇列中元素個數 */
count = QueueLength(Q);
printf("%2d 出隊_當前佇列中元素個數:%2d", outque, count);
show_queue(Q);
}
/* 獲得當前隊頭值 */
GetHead(Q, &outque);
printf("\n當前隊頭為:%d\n", outque);
printf("________________清空佇列_________________\n\n");
ClearQueue(&Q);
count = QueueLength(Q);
printf("當前佇列中元素個數:%2d", count);
show_queue(Q);
printf("________________銷燬佇列_________________\n\n");
DestoryQueue(&Q);
count = QueueLength(Q);
printf("當前佇列中元素個數:%2d\n\n", count);
return 0;
}