學習佇列 (轉)
/*
=====================================================================
作者:rerli
時間:2004-02-11
目的:學習佇列
=====================================================================
*/
/*
佇列是從日常排隊現象抽象出來的一種數學模型。當然資料結構中的佇列
遠沒有生活中的排隊靈活。資料結構中的佇列規定:資料只能從隊尾進,從隊
首出來。已經進入佇列的資料次序不能再做改變。這就叫做“先進先出”(FIFO)
或者說“後進後出”(LILO)。允許插入的一端稱為隊尾,通常用一個稱為尾指標
(rear)的指標指向隊尾元素,即尾指標總是指向最後被插入的元素;允許刪
除的一端稱為隊首,通常也用一個隊首指標(front)指向隊首元素的前一個位
置(當然也可以直接指向隊首元素,只是許多資料結構的書上都習慣這麼定義)。
與佇列類似,我們可以用一維陣列來模擬佇列這種資料結構,也可以用連結串列
來模擬。
根據以上描述,佇列可以整理出以下基本操作:
1、建立初始化:按約定置佇列為空狀態。
2、入佇列:在隊尾加入一個新資料項。
3、出佇列:從隊首取出一個資料項,並使餘下諸項向隊首移動。
4、佇列空:判斷佇列是否為空。
5、佇列滿:判斷佇列是否已滿。
從概念上說,佇列不存在“滿”狀態,其長度可以任意增加,
但實現(不論靜態或動態)中總有空間限制的。
下面我就來討論用陣列實現佇列結構。
假定佇列中元素的型別為T,佇列的最大長度為queue_size,在任何一刻佇列
首、尾位置分別用下標head、tail指向。
佇列初始狀態應為:head=0,tail=-1。根據佇列定義,head值應恆為0,
那麼每當出隊一個資料項,則必須多次移動操作(餘下諸項向隊首移動)。
顯然不能直接採用這種結構實現佇列。解決這個問題,可以從數學取模運算聯想
到一個解決辦法。比如x=(x+1) mod 100 ,則x的變化範圍在[0,99]之間,
超過100的又從0,1開始。這不就是我們所需要的嘛!許多書上把它叫作“迴圈
陣列”技術。即當入佇列時先移動tail(即tail=(tail+1) mod queue_size),
出佇列時先移動head(即head=(head+1) mod queue_size)。
在移動中,若head(或tail)值為queue_size-1,則移動後head(或tail)的值
就變成0了,對這種特徵就是一個環,只要陣列有空間,就可以入佇列。
用“迴圈陣列”實現佇列,必須注意怎樣判斷佇列的空與滿的狀態。除起始狀態
外。任何時刻tail所指為最後一個進入佇列的元素,而head所指的是剛剛出佇列的
那個元素原先所佔的位置。因此(head+1) mod queue_size才是真正當前佇列中首元
素位置。
採用條件:(tail+1) mod queue_size == head 作為“佇列滿”的判斷條件。
實際上此時佇列中還有一個空位置,這樣佇列的利用空間比定義的最大空間少一個
單元。假如把這個單元也利用上,則就不好判斷“滿”或“空”了(當head==tail)
,必須根據是tail追上了head,還是head追上了tail才能區分,這樣給處理帶來了
不便。
*/
#include
#include
#define NULL 0
typedef struct node
{
int data;
}NODE;
#define LEN sizeof(NODE)
/*佇列的需要變數*/
typedef enum {false,true}bool; /*定義bool型別*/
unsigned int head; /*定義隊首下標變數*/
unsigned int tail; /*定義隊尾下標變數*/
static NODE *queue=NULL; /*定義一個佇列*/
static unsigned int queue_size=0;/*佇列的大小*/
/*
========================
功能:初始化佇列的大小
返回:true or false
========================
*/
bool InitQueue(unsigned int size)
{
queue=(NODE *)malloc(size*LEN); /*開闢空間*/
if (queue==NULL) /*開闢空間失敗,則返回false*/
{
return false;
}
queue_size = size; /*儲存佇列空間大小值*/
head = queue_size-1;/*隊首下標賦初值*/
tail = queue_size-1;/*隊尾下標賦初值*/
return true; /*初始化成功,返回true*/
}
/*
======================
功能:釋放佇列的
返回:void
======================
*/
void FreeQueue()
{
free(queue);
/*
注意:這一點很重要。free()之後並不能將queue
置為NULL,所以我們一定要自己做。這樣能防止產生
“野指標”,即地址不確定的指標。
*/
queue = NULL;
}
/*
==========================
功能:判斷佇列是否已滿
返回:true or false
==========================
*/
bool Full()
{
return (((tail+1)%queue_size)==head);
}
/*
===========================
功能:判斷佇列是否為空
返回:true or false
===========================
*/
bool Empty(){
return (head==tail);
}
/*
========================
功能:入佇列
返回:true or false
========================
*/
bool Push(NODE p)
{
if (!Full()) /*佇列不滿,則入佇列;隊尾下標要加1*/
{
tail = (tail+1)%queue_size;
queue[tail] = p;
return true;
}
else
{
printf("queue is overflow !n");
return false;
}
}
/*
===================
功能:出佇列
返回:出佇列元素指標
===================
*/
NODE *Pop()
{
if (!Empty()) /*佇列不空,則出佇列;隊首下標要加1*/
{
head = (head+1)%queue_size;
return (&queue[head]);
}
else
{
printf("queue is empty !n");
return NULL;
}
}
void main(void)
{
NODE node1 = {3};
NODE *p;
if (!InitQueue(3)) /*初始化不成功,則退出*/
{
exit(0);
}
Push(node1);
/*去掉下面的註釋,你可以驗證講解中空間利用問題*/
/*
Push(node1);
Push(node1);
Push(node1);
*/
p =Pop();
printf("%d",p->data);
FreeQueue(); /*注意退出時釋放佇列記憶體*/
printf("n");
system("pause");
}
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10794571/viewspace-974828/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Redis 佇列學習記錄Redis佇列
- Laravel5.4 Queues佇列學習Laravel佇列
- 訊息佇列學習基礎佇列
- 訊息佇列學習腦圖佇列
- 資料結構學習之佇列資料結構佇列
- 訊息佇列Kafka學習總結佇列Kafka
- Android併發學習之阻塞佇列Android佇列
- JS資料結構學習:佇列JS資料結構佇列
- 多執行緒學習-Disruptor佇列執行緒佇列
- RabbitMQ 學習筆記 -- 12 死信佇列 DLX + TTL 方式實現延遲佇列MQ筆記佇列
- Laravel 佇列 --- database 驅動(今天剛學習了佇列,記錄下筆記)Laravel佇列Database筆記
- 微服務學習計劃——訊息佇列微服務佇列
- php使用佇列 SplQueue類學習記錄PHP佇列
- 深入學習Lock鎖(1)——佇列同步器佇列
- 2.1資料結構學習筆記--佇列資料結構筆記佇列
- 佇列、阻塞佇列佇列
- SQL 行轉列 PIVOT 學習示例SQL
- 學習JavaScript資料結構(一)——棧和佇列JavaScript資料結構佇列
- 笨辦法學C 練習42:棧和佇列佇列
- RabbitMQ學習(三)之 “訊息佇列高階使用”MQ佇列
- 前端學習 資料結構與演算法 快速入門 系列 —— 佇列和雙端佇列前端資料結構演算法佇列
- 佇列-單端佇列佇列
- 資料結構基礎學習之(棧和佇列)資料結構佇列
- [學習筆記] 單調佇列最佳化DP - DP筆記佇列
- 大二資料結構學習3(棧和佇列)資料結構佇列
- C# 使用執行緒池佇列(學習筆記)C#執行緒佇列筆記
- Java佇列學習第一篇之列介紹Java佇列
- 再談訊息佇列技術-轉佇列
- 佇列 和 迴圈佇列佇列
- 【佇列】【懶排序】佇列Q佇列排序
- 陣列模擬佇列 以及佇列的複用(環形佇列)陣列佇列
- 【GO語言學習】每日一題:根據身高重建佇列Go每日一題佇列
- Redis 學習筆記(六)Redis 如何實現訊息佇列Redis筆記佇列
- 佇列 手算到機算 入門 佇列 迴圈佇列佇列
- 圖解--佇列、併發佇列圖解佇列
- 單調佇列雙端佇列佇列
- 帶你玩轉RabbitMQ的五種佇列MQ佇列
- 佇列佇列
- 優先佇列的學習記錄--例題:Expedition(POJ2431)佇列