概述
一種更好的計算隊尾指針的方法。
隊尾指針新算法
一個新的計算隊尾指針的公式:
設模擬環形隊列的線性表長度是N,隊頭指針為head,隊尾指針為tail,則每增加一條記錄,就可以用一下方法計算新的隊尾指針: tail = (tail + 1) % N
環形隊列示意圖
思考
但是,我在移植到8266的代碼時,發現有點問題。
第一,head和tail應該是存儲該數組的下標而不是一個指向該數組元素的指針。如果tail是指針,那么 tail本質上是一個內存地址,*tail是指向該數組的某一元素。那么這算式tail = (tail + 1) % N其實是對某數組元素的內存地址+1,然后在用N求余。 所以head和tail應該是保存該數組的下標,而不是指向該數組元素的指針。
第二,由于原先的代碼,其隊尾指針總是指向最后一個入隊元素的下一個元素,而《算》給出的隊列,隊尾指針總是指向最后一個入隊的元素。如上圖,一個N=12的環形隊列,原先的代碼tail是指向第8個,《算》是指向第7個,由于我是在8266的示例代碼上修改的,所以《算》給出的隊尾指針算法需要調整一下:
//元素入隊之后 tail++;//tail指向最后一個入隊的下一個元素 tail=tail%N;//重新計算tail的數值123
新的數據結構
那么我就開始定義新的數據結構了,原先的數據結構是這樣的
typedefstruct{ uint8_t*p_o;//指向原點的指針,用來數組首地址 uint8_t*volatilep_r;//讀取指針,相當于head uint8_t*volatilep_w;//寫入指針,相到于tail volatileint32_tfill_cnt;//隊列計數 int32_tsize;//緩沖區的大小 }RINGBUF;
新的數據結構:
typedefstruct{ char*buf;//指向隊列數組的指針 unsignedintlength;//數組長度 unsignedinthead;//隊頭,存儲數組下標 unsignedinttail;//隊尾,存儲數組下標 intfill_cnt;//隊列計數 }RINGBUF;
判斷是否空隊列
一開始,本來想用if(head==tail)來判斷隊列是否為空的,但是由于tail保存的是入隊元素的下一個數組下標,當隊列填滿的時候,tail的下標正好等于head,所以不能通過if(head==tail)來判斷隊列是否為空,
完整代碼
下面是完整的數組環形隊列代碼,運行環境是VS2015,主函數里進行了簡單的測試:
// RingBuf.cpp :定義控制臺應用程序的入口點。 // #include"stdafx.h" typedefstruct{ char*buf;//指向隊列數組的指針 unsignedintlength;//長度 unsignedinthead;//隊頭 unsignedinttail;//隊尾 intfill_cnt;//隊列計數 }RINGBUF; intRINGBUF_Init(RINGBUF*r,chararray[],size_tlen) { if(len<2?||?array==NULL){ ????????return?false; ????} ????r->buf=array; r->length=len; r->fill_cnt=0; r->head=r->tail=0; returntrue; } intRINGBUF_Put(RINGBUF*r,chardata) { //當tail+1等于head時,說明隊列已滿 if(r->fill_cnt>=r->length){ printf("BUFFULL! "); returnfalse;//如果緩沖區滿了,則返回錯誤 } r->buf[r->tail]=data; r->tail++; r->fill_cnt++; //計算tail是否超出數組范圍,如果超出則自動切換到0 r->tail=r->tail%r->length; returntrue; } intRINGBUF_Get(RINGBUF*r,char*c,unsignedintlength) { //當tail等于head時,說明隊列空 if(r->fill_cnt<=0)?{ ????????printf("BUF?EMPTY! "); ????????return?false; ????} ????//最多只能讀取r->length長度數據 if(length>r->length){ length=r->length; } inti; for(i=0;ifill_cnt--; *c=r->buf[r->head++];//返回數據給*c *c++; //計算head自加后的下標是否超出數組范圍,如果超出則自動切換到0 r->head=r->head%r->length; } returntrue; } #defineBUF_LEN5 RINGBUFBUFF; charbuf[BUF_LEN]; intmain() { RINGBUF_Init(&BUFF,buf,sizeof(buf)); printf("1、逐個讀取數據測試 "); intlength=5; for(inti=0;i
控制臺打印信息如下:
1、逐個讀取數據測試
每次讀取1個字節:buf pop : 0
每次讀取1個字節:buf pop : 1
每次讀取1個字節:buf pop : 2
每次讀取1個字節:buf pop : 3
每次讀取1個字節:buf pop : 42、一次性讀取測試
一次性讀取5個字節:buf pop : 123453、放入超過緩沖區長度(BUF_LEN+1)數據測試:
BUF FULL!
一次性讀取(BUF_LEN+1)個字節測試:buf pop : 123454、讀取空緩沖區測試:
BUF EMPTY!
請按任意鍵繼續…后話
由于存在幾種隊尾指向元素的方式,以上代碼是還可以在修改優化一下的。
《算》的代碼是不需要考慮隊列是否滿了,他只需要直接覆蓋舊的元素即可,我的需求是需要判斷隊列是否填滿,以免舊的元素被覆蓋。審核編輯:湯梓紅
-
算法
+關注
關注
23文章
4630瀏覽量
93352 -
指針
+關注
關注
1文章
481瀏覽量
70608 -
代碼
+關注
關注
30文章
4825瀏覽量
69043 -
數據結構
+關注
關注
3文章
573瀏覽量
40230 -
數組
+關注
關注
1文章
417瀏覽量
26028
原文標題:一種數組環形隊列的數據結構
文章出處:【微信號:技術讓夢想更偉大,微信公眾號:技術讓夢想更偉大】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論