佇列之鏈佇列詳解(C語言版)
阿新 • • 發佈:2021-02-15
文章目錄
前言
大家好,越努力,越幸運。本篇文章小猿將跟您分享資料結構佇列中的鏈佇列,希望對您有所幫助。
一、鏈佇列的定義
首先我們來看看什麼是佇列?佇列是一種先進先出(FIFO)的線性表,它只允許在表的一端進行插入,而在另一端刪除元素。這和我們日常生活中的排隊是一致的,最早進入佇列的元素最早離開。佇列的結構圖如下所示:
明白了佇列之後,鏈佇列就非常簡單了,用連結串列表示的佇列就簡稱為鏈佇列。一個鏈佇列顯然需要兩個分別指示隊頭和隊尾的指標(分別稱為頭指標和尾指標)才能惟一確定。
二、鏈佇列的結構
結構圖
程式碼描述
//資料型別
#define ElemType int
//佇列結點型別
typedef struct QueueNode
{
ElemType data; //資料域
struct QueueNode *next; //指標域
}QueueNode;
//鏈式佇列管理結構
typedef struct LinkQueue
{
QueueNode *front; //隊頭指標
QueueNode *tail; //隊尾指標
}LinkQueue;
三、鏈佇列的常用操作
初始化
//初始化佇列
void InitQueue(LinkQueue *Q)
{
//申請頭結點記憶體空間
QueueNode *s = (QueueNode *)malloc(sizeof(QueueNode));
assert(s != NULL);
//初始化時,將頭指標和尾指標都指向頭結點
Q->front = Q->tail = s;
//將頭結點的下一結點賦空
Q->tail->next = NULL;
}
入隊
//入隊操作:在隊尾執行插入操作
void EnQueue(LinkQueue *Q, ElemType x)
{
//申請佇列結點
QueueNode *s = (QueueNode *)malloc(sizeof(QueueNode) );
assert(s != NULL);
//為申請的佇列結點賦值
s->data = x;
s->next = NULL;
//將申請的佇列結點插入到隊尾
Q->tail->next = s;
//更改佇列管理結點中尾指標的指向
Q->tail = s;
}
出隊
//出隊操作:刪除隊頭的第一個有效結點
void DeQueue(LinkQueue *Q)
{
//如果隊中無有效結點,無需進行操作
if(Q->front == Q->tail)
return;
//獲取隊頭的第一個有效結點
QueueNode *p = Q->front->next;
//將隊頭的第一個有效結點從佇列中斷開
Q->front->next = p->next;
//釋放該結點
free(p);
//如果刪除的結點是最後一個有效結點,需要更改尾指標的指向
if(p == Q->tail)
Q->tail = Q->front;
}
列印佇列資料
//列印佇列內的資料
void ShowQueue(LinkQueue *Q)
{
//獲取佇列中第一個有效結點
QueueNode *p = Q->front->next;
printf("Front:>");
//將佇列中每個有效結點中的資料列印
while(p != NULL)
{
printf("%d ",p->data);
p = p->next;
}
printf("<:Tail.\n");
}
獲取隊頭元素
//獲取隊頭元素
void GetHead(LinkQueue *Q, ElemType *v)
{
//如果隊中無有效結點,無需進行操作
if(Q->front == Q->tail)
return;
//獲取隊頭的第一個有效結點
QueueNode *p = Q->front->next;
//返回隊頭第一個有效結點資料
*v = p->data;
}
求佇列長度
//求佇列的長度
int Length(LinkQueue *Q)
{
int len = 0;//初始長度為0
//獲取隊頭的第一個有效結點
QueueNode *p = Q->front->next;
//遍歷佇列,獲取一個結點,將佇列長度加一
while(p != NULL)
{
len++;
p = p->next;
}
//返回長度值
return len;
}
清空佇列
//清空佇列:釋放所有的有效結點
void ClearQueue(LinkQueue *Q)
{
//如果隊中無有效結點,無需進行操作
if(Q->front == Q->tail)
return;
//獲取隊頭的第一個有效結點
QueueNode *p = Q->front->next;
//遍歷佇列中的有效結點
while(p != NULL)
{
//移除結點
Q->front->next = p->next;
//釋放結點
free(p);
//指向下一個結點
p = Q->front->next;
}
Q->tail = Q->front;
}
銷燬佇列
//銷燬佇列
void DestroyQueue(LinkQueue *Q)
{
//清空佇列
ClearQueue(Q);
//釋放頭結點
free(Q->front);
//將管理結點中的頭指標和尾指標都指向空
Q->front = Q->tail = NULL;
}
結語
對鏈佇列的介紹就到這裡啦,希望這篇文章能給予你一些幫助,感謝各位人才的:點贊、收藏和評論,我們下次見。
附錄
以下提供鏈佇列的測試程式碼
LinkQueue.h
#ifndef __LINKQUEUE_H__
#define __LINKQUEUE_H__
#include<stdio.h>
#include<malloc.h>
#include<assert.h>
//資料型別
#define ElemType int
//佇列結點型別
typedef struct QueueNode
{
ElemType data; //資料域
struct QueueNode *next; //指標域
}QueueNode;
//鏈式佇列管理結構
typedef struct LinkQueue
{
QueueNode *front; //隊頭指標
QueueNode *tail; //隊尾指標
}LinkQueue;
void InitQueue(LinkQueue *Q);
void EnQueue(LinkQueue *Q, ElemType x);
void ShowQueue(LinkQueue *Q);
void DeQueue(LinkQueue *Q);
void GetHead(LinkQueue *Q, ElemType *v);
int Length(LinkQueue *Q);
void ClearQueue(LinkQueue *Q);
void DestroyQueue(LinkQueue *Q);
#endif //__LINKQUEUE_H__
LinkQueue.cpp
#include"LinkQueue.h"
//初始化佇列
void InitQueue(LinkQueue *Q)
{
//申請頭結點記憶體空間
QueueNode *s = (QueueNode *)malloc(sizeof(QueueNode));
assert(s != NULL);
//初始化時,將頭指標和尾指標都指向頭結點
Q->front = Q->tail = s;
//將頭結點的下一結點賦空
Q->tail->next = NULL;
}
//入隊操作:在隊尾執行插入操作
void EnQueue(LinkQueue *Q, ElemType x)
{
//申請佇列結點
QueueNode *s = (QueueNode *)malloc(sizeof(QueueNode));
assert(s != NULL);
//為申請的佇列結點賦值
s->data = x;
s->next = NULL;
//將申請的佇列結點插入到隊尾
Q->tail->next = s;
//更改佇列管理結點中尾指標的指向
Q->tail = s;
}
//列印佇列內的資料
void ShowQueue(LinkQueue *Q)
{
//獲取佇列中第一個有效結點
QueueNode *p = Q->front->next;
printf("Front:>");
//將佇列中每個有效結點中的資料列印
while(p != NULL)
{
printf("%d ",p->data);
p = p->next;
}
printf("<:Tail.\n");
}
//出隊操作:刪除隊頭的第一個有效結點
void DeQueue(LinkQueue *Q)
{
//如果隊中無有效結點,無需進行操作
if(Q->front == Q->tail)
return;
//獲取隊頭的第一個有效結點
QueueNode *p = Q->front->next;
//將隊頭的第一個有效結點從佇列中斷開
Q->front->next = p->next;
//釋放該結點
free(p);
//如果刪除的結點是最後一個有效結點,需要更改尾指標的指向
if(p == Q->tail)
Q->tail = Q->front;
}
//獲取隊頭元素
void GetHead(LinkQueue *Q, ElemType *v)
{
//如果隊中無有效結點,無需進行操作
if(Q->front == Q->tail)
return;
//獲取隊頭的第一個有效結點
QueueNode *p = Q->front->next;
//返回隊頭第一個有效結點資料
*v = p->data;
}
//求佇列的長度
int Length(LinkQueue *Q)
{
int len = 0;//初始長度為0
//獲取隊頭的第一個有效結點
QueueNode *p = Q->front->next;
//遍歷佇列,獲取一個結點,將佇列長度加一
while(p != NULL)
{
len++;
p = p->next;
}
//返回長度值
return len;
}
//清空佇列:釋放所有的有效結點
void ClearQueue(LinkQueue *Q)
{
//如果隊中無有效結點,無需進行操作
if(Q->front == Q->tail)
return;
//獲取隊頭的第一個有效結點
QueueNode *p = Q->front->next;
//遍歷佇列中的有效結點
while(p != NULL)
{
//移除結點
Q->front->next = p->next;
//釋放結點
free(p);
//指向下一個結點
p = Q->front->next;
}
Q->tail = Q->front;
}
//銷燬佇列
void DestroyQueue(LinkQueue *Q)
{
//清空佇列
ClearQueue(Q);
//釋放頭結點
free(Q->front);
//將管理結點中的頭指標和尾指標都指向空
Q->front = Q->tail = NULL;
}
Main.cpp
#include"LinkQueue.h"
void main()
{
LinkQueue Q;
InitQueue(&Q);//初始化佇列
for(int i=1; i<=10; ++i)
{
EnQueue(&Q,i);//入隊操作
}
ShowQueue(&Q);
DeQueue(&Q);
DeQueue(&Q);
ShowQueue(&Q);
printf("Len = %d\n",Length(&Q));
}