0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

一種數(shù)組環(huán)形隊(duì)列的數(shù)據(jù)結(jié)構(gòu)

技術(shù)讓夢(mèng)想更偉大 ? 來源:CSDN-閼男秀 ? 2023-04-26 09:17 ? 次閱讀

概述

一種更好的計(jì)算隊(duì)尾指針的方法。

隊(duì)尾指針新算法

一個(gè)新的計(jì)算隊(duì)尾指針的公式:

設(shè)模擬環(huán)形隊(duì)列的線性表長(zhǎng)度是N,隊(duì)頭指針為head,隊(duì)尾指針為tail,則每增加一條記錄,就可以用一下方法計(jì)算新的隊(duì)尾指針: tail = (tail + 1) % N

780c9d90-e3b6-11ed-ab56-dac502259ad0.jpg

環(huán)形隊(duì)列示意圖

思考

但是,我在移植到8266的代碼時(shí),發(fā)現(xiàn)有點(diǎn)問題。

第一,head和tail應(yīng)該是存儲(chǔ)該數(shù)組的下標(biāo)而不是一個(gè)指向該數(shù)組元素的指針。如果tail是指針,那么 tail本質(zhì)上是一個(gè)內(nèi)存地址,*tail是指向該數(shù)組的某一元素。那么這算式tail = (tail + 1) % N其實(shí)是對(duì)某數(shù)組元素的內(nèi)存地址+1,然后在用N求余。 所以head和tail應(yīng)該是保存該數(shù)組的下標(biāo),而不是指向該數(shù)組元素的指針。

第二,由于原先的代碼,其隊(duì)尾指針總是指向最后一個(gè)入隊(duì)元素的下一個(gè)元素,而《算》給出的隊(duì)列,隊(duì)尾指針總是指向最后一個(gè)入隊(duì)的元素。如上圖,一個(gè)N=12的環(huán)形隊(duì)列,原先的代碼tail是指向第8個(gè),《算》是指向第7個(gè),由于我是在8266的示例代碼上修改的,所以《算》給出的隊(duì)尾指針?biāo)惴ㄐ枰{(diào)整一下:

//元素入隊(duì)之后
tail++;//tail指向最后一個(gè)入隊(duì)的下一個(gè)元素
tail=tail%N;//重新計(jì)算tail的數(shù)值123

新的數(shù)據(jù)結(jié)構(gòu)

那么我就開始定義新的數(shù)據(jù)結(jié)構(gòu)了,原先的數(shù)據(jù)結(jié)構(gòu)是這樣的

typedefstruct{
uint8_t*p_o;//指向原點(diǎn)的指針,用來數(shù)組首地址
uint8_t*volatilep_r;//讀取指針,相當(dāng)于head
uint8_t*volatilep_w;//寫入指針,相到于tail
volatileint32_tfill_cnt;//隊(duì)列計(jì)數(shù)
int32_tsize;//緩沖區(qū)的大小
}RINGBUF;

新的數(shù)據(jù)結(jié)構(gòu):

typedefstruct{
char*buf;//指向隊(duì)列數(shù)組的指針
unsignedintlength;//數(shù)組長(zhǎng)度
unsignedinthead;//隊(duì)頭,存儲(chǔ)數(shù)組下標(biāo)
unsignedinttail;//隊(duì)尾,存儲(chǔ)數(shù)組下標(biāo)
intfill_cnt;//隊(duì)列計(jì)數(shù)
}RINGBUF;

判斷是否空隊(duì)列

一開始,本來想用if(head==tail)來判斷隊(duì)列是否為空的,但是由于tail保存的是入隊(duì)元素的下一個(gè)數(shù)組下標(biāo),當(dāng)隊(duì)列填滿的時(shí)候,tail的下標(biāo)正好等于head,所以不能通過if(head==tail)來判斷隊(duì)列是否為空,

完整代碼

下面是完整的數(shù)組環(huán)形隊(duì)列代碼,運(yùn)行環(huán)境是VS2015,主函數(shù)里進(jìn)行了簡(jiǎn)單的測(cè)試:

// RingBuf.cpp :定義控制臺(tái)應(yīng)用程序的入口點(diǎn)。
//

#include"stdafx.h"

typedefstruct{
char*buf;//指向隊(duì)列數(shù)組的指針
unsignedintlength;//長(zhǎng)度
unsignedinthead;//隊(duì)頭
unsignedinttail;//隊(duì)尾
intfill_cnt;//隊(duì)列計(jì)數(shù)
}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)
{
//當(dāng)tail+1等于head時(shí),說明隊(duì)列已滿
if(r->fill_cnt>=r->length){
printf("BUFFULL!
");
returnfalse;//如果緩沖區(qū)滿了,則返回錯(cuò)誤
}

r->buf[r->tail]=data;
r->tail++;
r->fill_cnt++;
//計(jì)算tail是否超出數(shù)組范圍,如果超出則自動(dòng)切換到0
r->tail=r->tail%r->length;
returntrue;
}

intRINGBUF_Get(RINGBUF*r,char*c,unsignedintlength)
{
//當(dāng)tail等于head時(shí),說明隊(duì)列空
if(r->fill_cnt<=0)?{
????????printf("BUF?EMPTY!
");
????????return?false;
????}

????//最多只能讀取r->length長(zhǎng)度數(shù)據(jù)
if(length>r->length){
length=r->length;
}

inti;
for(i=0;ifill_cnt--;
*c=r->buf[r->head++];//返回?cái)?shù)據(jù)給*c
*c++;
//計(jì)算head自加后的下標(biāo)是否超出數(shù)組范圍,如果超出則自動(dòng)切換到0
r->head=r->head%r->length;
}
returntrue;
}



#defineBUF_LEN5
RINGBUFBUFF;
charbuf[BUF_LEN];

intmain()
{
RINGBUF_Init(&BUFF,buf,sizeof(buf));

printf("1、逐個(gè)讀取數(shù)據(jù)測(cè)試
");
intlength=5;
for(inti=0;i

控制臺(tái)打印信息如下:

1、逐個(gè)讀取數(shù)據(jù)測(cè)試
每次讀取1個(gè)字節(jié):buf pop : 0
每次讀取1個(gè)字節(jié):buf pop : 1
每次讀取1個(gè)字節(jié):buf pop : 2
每次讀取1個(gè)字節(jié):buf pop : 3
每次讀取1個(gè)字節(jié):buf pop : 4

2、一次性讀取測(cè)試
一次性讀取5個(gè)字節(jié):buf pop : 12345

3、放入超過緩沖區(qū)長(zhǎng)度(BUF_LEN+1)數(shù)據(jù)測(cè)試:
BUF FULL!
一次性讀取(BUF_LEN+1)個(gè)字節(jié)測(cè)試:buf pop : 12345

4、讀取空緩沖區(qū)測(cè)試:
BUF EMPTY!
請(qǐng)按任意鍵繼續(xù)…

后話

由于存在幾種隊(duì)尾指向元素的方式,以上代碼是還可以在修改優(yōu)化一下的。

《算》的代碼是不需要考慮隊(duì)列是否滿了,他只需要直接覆蓋舊的元素即可,我的需求是需要判斷隊(duì)列是否填滿,以免舊的元素被覆蓋。

審核編輯:湯梓紅

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 算法
    +關(guān)注

    關(guān)注

    23

    文章

    4612

    瀏覽量

    92910
  • 指針
    +關(guān)注

    關(guān)注

    1

    文章

    480

    瀏覽量

    70564
  • 代碼
    +關(guān)注

    關(guān)注

    30

    文章

    4788

    瀏覽量

    68625
  • 數(shù)據(jù)結(jié)構(gòu)

    關(guān)注

    3

    文章

    573

    瀏覽量

    40132
  • 數(shù)組
    +關(guān)注

    關(guān)注

    1

    文章

    417

    瀏覽量

    25947

原文標(biāo)題:一種數(shù)組環(huán)形隊(duì)列的數(shù)據(jù)結(jié)構(gòu)

文章出處:【微信號(hào):技術(shù)讓夢(mèng)想更偉大,微信公眾號(hào):技術(shù)讓夢(mèng)想更偉大】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    嵌入式常用數(shù)據(jù)結(jié)構(gòu)------隊(duì)列操作簡(jiǎn)介

    嵌入式常用數(shù)據(jù)結(jié)構(gòu)------隊(duì)列操作簡(jiǎn)介隊(duì)列是嵌入式軟件中常用的一種數(shù)據(jù)結(jié)構(gòu)。什么是隊(duì)列呢?在生活中,我們都知道,買東西時(shí)要排隊(duì),比如最近
    發(fā)表于 06-17 17:30

    收藏 | 程序員面試,你必須知道的8大數(shù)據(jù)結(jié)構(gòu)

    數(shù)據(jù)結(jié)構(gòu)首先列出些最常見的數(shù)據(jù)結(jié)構(gòu),我們將逐說明:數(shù)組隊(duì)列鏈表樹圖字典樹(這是
    發(fā)表于 09-30 09:35

    常見的數(shù)據(jù)結(jié)構(gòu)

    胡亂的,這就要求我們選擇一種好的方式來存儲(chǔ)數(shù)據(jù),而這也是數(shù)據(jù)結(jié)構(gòu)的核心內(nèi)容。數(shù)據(jù)存儲(chǔ)直以來大家面對(duì)的數(shù)
    發(fā)表于 05-10 07:58

    數(shù)據(jù)結(jié)構(gòu)隊(duì)列順序及其構(gòu)造

    數(shù)據(jù)結(jié)構(gòu)隊(duì)列順序隊(duì)列構(gòu)造順序隊(duì)列順序隊(duì)列的初始化判斷隊(duì)列是否滿判斷
    發(fā)表于 12-17 06:11

    實(shí)現(xiàn)隊(duì)列環(huán)形緩沖的方法

    串口隊(duì)列環(huán)形緩沖區(qū)隊(duì)列串口環(huán)形緩沖的好處代碼實(shí)現(xiàn)隊(duì)列??要實(shí)現(xiàn)隊(duì)列
    發(fā)表于 02-21 07:11

    環(huán)形隊(duì)列的相關(guān)資料分享

    的小伙伴,對(duì)隊(duì)列肯定不會(huì)陌生,隊(duì)列相對(duì)來說是比較簡(jiǎn)單的數(shù)據(jù)結(jié)構(gòu),典型特點(diǎn)是FIFO,即First in First out,先進(jìn)先出,就像我們?nèi)粘E抨?duì)買票樣,先到的人先買票,先從購(gòu)票
    發(fā)表于 02-23 06:10

    數(shù)據(jù)結(jié)構(gòu)的簡(jiǎn)介和線性表及棧隊(duì)列數(shù)組的詳細(xì)說明

    兩項(xiàng)基本任務(wù):數(shù)據(jù)表示,數(shù)據(jù)處理 軟件系統(tǒng)生存期:軟件計(jì)劃,需求分析,軟件設(shè)計(jì),軟件編碼,軟件測(cè)試,軟件維護(hù) 由一種邏輯結(jié)構(gòu)組基本運(yùn)
    發(fā)表于 01-06 08:00 ?0次下載

    深度解析數(shù)據(jù)結(jié)構(gòu)與算法篇之隊(duì)列環(huán)形隊(duì)列的實(shí)現(xiàn)

    01 — 隊(duì)列簡(jiǎn)介 隊(duì)列先進(jìn)先出的數(shù)據(jù)結(jié)構(gòu),有個(gè)元素進(jìn)入隊(duì)列稱為入對(duì)(enqueue),刪除元素稱為出隊(duì)(dequeue),
    的頭像 發(fā)表于 06-18 10:07 ?1931次閱讀

    STM32串口環(huán)形緩沖--使用隊(duì)列實(shí)現(xiàn)(開放源碼)

    串口隊(duì)列環(huán)形緩沖區(qū)隊(duì)列串口環(huán)形緩沖的好處代碼實(shí)現(xiàn)隊(duì)列??要實(shí)現(xiàn)隊(duì)列
    發(fā)表于 12-24 19:04 ?28次下載
    STM32串口<b class='flag-5'>環(huán)形</b>緩沖--使用<b class='flag-5'>隊(duì)列</b>實(shí)現(xiàn)(開放源碼)

    SystemVerilog中可以嵌套的數(shù)據(jù)結(jié)構(gòu)

    SystemVerilog中除了數(shù)組、隊(duì)列和關(guān)聯(lián)數(shù)組數(shù)據(jù)結(jié)構(gòu),這些數(shù)據(jù)結(jié)構(gòu)還可以嵌套。
    的頭像 發(fā)表于 11-03 09:59 ?1606次閱讀

    嵌入式環(huán)形隊(duì)列和消息隊(duì)列的實(shí)現(xiàn)

    嵌入式環(huán)形隊(duì)列和消息隊(duì)列是實(shí)現(xiàn)數(shù)據(jù)緩存和通信的常見數(shù)據(jù)結(jié)構(gòu),廣泛應(yīng)用于嵌入式系統(tǒng)中的通信協(xié)議和領(lǐng)域。
    的頭像 發(fā)表于 04-14 11:52 ?1561次閱讀

    數(shù)據(jù)結(jié)構(gòu)解決滑動(dòng)窗口問題

    前文用 [單調(diào)棧解決三道算法問題]介紹了單調(diào)棧這種特殊數(shù)據(jù)結(jié)構(gòu),本文寫個(gè)類似的數(shù)據(jù)結(jié)構(gòu)「單調(diào)隊(duì)列」。 也許這種數(shù)據(jù)結(jié)構(gòu)的名字你沒聽過,其
    的頭像 發(fā)表于 04-19 10:50 ?659次閱讀
    <b class='flag-5'>數(shù)據(jù)結(jié)構(gòu)</b>解決滑動(dòng)窗口問題

    redis的五種數(shù)據(jù)類型底層數(shù)據(jù)結(jié)構(gòu)

    Redis是一種內(nèi)存數(shù)據(jù)存儲(chǔ)系統(tǒng),支持多種數(shù)據(jù)結(jié)構(gòu)。這些數(shù)據(jù)結(jié)構(gòu)不僅可以滿足常見的存儲(chǔ)需求,還能夠通過其底層數(shù)據(jù)結(jié)構(gòu)提供高效的操作和查詢。以
    的頭像 發(fā)表于 11-16 11:18 ?714次閱讀

    redis數(shù)據(jù)結(jié)構(gòu)的底層實(shí)現(xiàn)

    Redis是一種內(nèi)存鍵值數(shù)據(jù)庫(kù),常用于緩存、消息隊(duì)列、實(shí)時(shí)數(shù)據(jù)分析等場(chǎng)景。它的高性能得益于其精心設(shè)計(jì)的數(shù)據(jù)結(jié)構(gòu)和底層實(shí)現(xiàn)。本文將詳細(xì)介紹Re
    的頭像 發(fā)表于 12-05 10:14 ?621次閱讀

    嵌入式環(huán)形隊(duì)列與消息隊(duì)列的實(shí)現(xiàn)原理

    嵌入式環(huán)形隊(duì)列,也稱為環(huán)形緩沖區(qū)或循環(huán)隊(duì)列,是一種先進(jìn)先出(FIFO)的數(shù)據(jù)結(jié)構(gòu),用于在固定大小
    的頭像 發(fā)表于 09-02 15:29 ?529次閱讀