在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

深度解析數據結構與算法篇之隊列及環形隊列的實現

Android編程精選 ? 來源:編程學習總站 ? 作者:寫代碼的牛頓 ? 2021-06-18 10:07 ? 次閱讀

01

隊列簡介

隊列是種先進先出的數據結構,有個元素進入隊列稱為入對(enqueue),刪除元素稱為出隊(dequeue),隊列有對頭(head)和對尾(tail),當有元素進入隊列時就放在對尾的位置。

02

環形隊列的實現

要想將元素放入隊列我們必須知道對頭和隊尾,在隊列長度不能無限大的條件下我們還要知道隊列的最大容量,我們還想知道隊列大小,所以隊列內部能必須記錄當前元素數量。現在我們定義一個結構體如下用于描述隊列。

#define NAN (0xFFFFFE) typedef struct queue_arr{ int head; int tail; int cap; int size; int *arr; }queue_arr_t;

head是對列頭,tail是對尾,cap記錄隊列的最大容量,size記錄當前隊列大小,arr指針保存一塊內存的首地址。下面我們定義隊列操作函數。

extern void queue_arr_init(queue_arr_t *q, int capacity); //隊列初始化 extern void enqueue_arr(queue_arr_t *q, int data); //入隊 extern int dequeue_arr(queue_arr_t *q); //出隊 extern void queue_arr_destroy(queue_arr_t *q); //銷毀隊列 extern bool queue_arr_is_full(queue_arr_t *q); //判斷隊列是否滿 extern bool queue_arr_is_empty(queue_arr_t *q); //判斷隊列是否為空 extern int queue_arr_length(queue_arr_t *q); //獲取隊列長度

隊列初始化

void queue_arr_init(queue_arr_t *q, int capacity){ if(q == NULL || capacity 《= 0){ return; } q-》head = 0; q-》tail = 0; q-》size = 0; q-》arr = malloc(capacity * sizeof(int)); q-》cap = capacity; }

入隊

void enqueue_arr(queue_arr_t *q, int data){ if(q == NULL){ return; } if(queue_arr_is_full(q)){ return; } //循環重用使用過的內存 if(q-》tail 》= q-》cap){ q-》tail = 0; } q-》arr[q-》tail++] = data; q-》size++; }

隊列容量有限,在進行入隊前一定對隊列進行判斷是否已滿。

出隊

int dequeue_arr(queue_arr_t *q){ if(q == NULL){ return NAN; } if(queue_arr_is_empty(q)){ return NAN; } if(q-》head 》= q-》cap){ q-》head = 0; } q-》size--; return q-》arr[q-》head++]; }

出隊時一定要對隊列進行判斷是否已空。

判斷隊列是否已滿

bool queue_arr_is_full(queue_arr_t *q){ if(q == NULL){ return false; } return q-》size == q-》cap ? true : false; }

判斷隊列是否已空

bool queue_arr_is_empty(queue_arr_t *q){ if(q == NULL){ return true; } return q-》size == 0 ? true : false; }

獲取隊列長度

int queue_arr_length(queue_arr_t *q){ if(q == NULL){ return 0; } return q-》size; }

銷毀隊列

void queue_arr_destroy(queue_arr_t *q){ if(q == NULL){ return; } if(q-》arr){ free(q-》arr); } q-》arr = NULL; q-》tail = 0; q-》head = 0; q-》cap = 0; q-》size = 0; }

03

鏈式隊列的實現

為了避免隊列元素的移動我們實現了環形隊列,但是通過申請一塊內存空間實現隊列在隊列大小未知的場景下無法滿足我們不斷加入元素進入隊列的需求,這個時候就需要一種無需知道隊列的最大容量,且能動態插入數據和取輸出的隊列實現。

我們知道鏈表能滿足這樣的需求,那么我們可以采用鏈表的實現方式實現隊列。下面我們分別定義一個結構體用于描述鏈式隊列和隊列結點并聲明隊列操作函數。

typedef struct node{ int data; struct node *next; }node_t; typedef struct queue{ node_t *head; node_t *tail; }queue_t; extern void queue_init(queue_t *q); //隊列初始化 extern void enqueue(queue_t *q, int data); //數據入隊 extern int dequeue(queue_t *q); //數據出隊列 extern int queue_length(queue_t *q); //獲取隊列長度 extern void queue_destroy(queue_t *q); //銷毀隊列

隊列結點的next指針像單鏈表一樣指向下一個結點,我們重點關注queue_t的定義,head是隊列頭,tail是對尾,有了對頭和對尾就能快速的從對尾插入數據從對頭取出數據。

隊列初始化

void queue_init(queue_t *q){ if(q == NULL){ return; } q-》head = NULL; q-》tail = NULL; }

入隊

元素每次進入隊列都需要新建一個結點,為了方便我們定義一個新建結點函數new_node,函數實現如下:

static node_t *new_node(int data){ node_t *node = (node_t *)malloc(sizeof(node_t)); if(node == NULL){ return NULL; } node-》next = NULL; node-》data = data; return node; }

入隊函數實現如下:

void enqueue(queue_t *q, int data){ if(q == NULL){ return; } node_t *node = new_node(data); //新建一個結點 if(node == NULL){ return; } if(q-》head == NULL && q-》tail == NULL){ //首次插入一個結點 q-》tail = node; q-》head = node; return; } q-》tail-》next = node; q-》tail = node; }

入隊前要進行判斷隊列里是否有結點,這里通過隊頭和對尾是否為空指針進行判斷,如果隊列里沒有結點則直接將對頭和隊尾指向插入的結點,否則結點則通過隊尾tail獲取到隊列最后的結點,并將最后結點的next指針指向新插入的結點,最后更新隊尾。

出隊

每次從隊列移除一個元素都需要釋放隊列結點內存,為了方便我們定義一個是否結點內存函數,函數實現如下:

static void free_node(node_t *node){ if(node == NULL){ return; } free(node); node-》next = NULL; }

出隊函數實現如下:

int dequeue(queue_t *q){ if(q == NULL){ return NAN; } if(q-》head == NULL && q-》tail == NULL){ return NAN; } node_t *node = q-》head; int data = node-》data; if(q-》head-》next == q-》tail){ //只有一個結點 q-》head = NULL; q-》tail = NULL; }else{ //不止一個結點 q-》head = q-》head-》next; } node-》next = NULL; free_node(node); return data; }

出隊同樣要判斷隊列里是否有結點,沒有結點則返回一個非法值,否則進行判斷是否只有一個結點,若只有一個結點則直接返回頭結點,并將對頭和隊尾指針置為空指針,否則獲取隊列頭結點并更新對頭指針。

獲取隊列長度

int queue_length(queue_t *q){ if(q == NULL){ return 0; } node_t *node = q-》head; if(node == NULL){ return 0; } int length = 1; while(node != q-》tail){ node = node-》next; length++; } return length; }

獲取隊列長度只要從隊列頭結點不斷的遍歷隊列,判斷當前結點是否已到隊列尾部,最后返回隊列長度。

銷毀隊列

void queue_destroy(queue_t *q){ if(q == NULL){ return; } node_t *node = q-》head; if(node == NULL){ return; } node_t *temp = NULL; while(node-》next != q-》tail){ temp = node; node = node-》next; free_node(temp); temp = NULL; } free_node(node); q-》tail = NULL; q-》head = NULL; }

04

結果驗證

下面我們寫一個小程序驗證隊列實現是否正確。

#include 《stdio.h》 #include “queue.h” int main() { queue_t queue; int i = 0; queue_init(&queue); //隊列初始化 printf(“入隊順序 ”); for(i = 0; i 《 5; i++){ printf(“%d ,”, i + 1); enqueue(&queue, i + 1); } printf(“ ”); printf(“隊列長度: %d ”, queue_length(&queue)); printf(“取出隊列一個數據:%d ”, dequeue(&queue)); printf(“取出隊列一個數據:%d ”, dequeue(&queue)); printf(“隊列長度: %d ”, queue_length(&queue)); printf(“銷毀隊列 ”); queue_destroy(&queue); printf(“ ”); printf(“大小固定的隊列測試 ”); queue_arr_t queue2; queue_arr_init(&queue2, 6); printf(“入隊順序 ”); for(i = 10; i 《 16; i++){ printf(“%d ,”, i); enqueue_arr(&queue2, i); } printf(“ ”); if(queue_arr_is_full(&queue2)){ printf(“隊列已滿 ”); }else{ printf(“隊列未滿 ”); } printf(“取出隊列一個數據:%d ”, dequeue_arr(&queue2)); printf(“取出隊列一個數據:%d ”, dequeue_arr(&queue2)); if(queue_arr_is_full(&queue2)){ printf(“隊列已滿 ”); }else{ printf(“隊列未滿 ”); } printf(“隊列長度是:%d ”, queue_arr_length(&queue2)); printf(“銷毀隊列 ”); queue_arr_destroy(&queue2); if(queue_arr_is_empty(&queue2)){ printf(“隊列已空 ”); }else{ printf(“隊列未空 ”); } return 0; }

編譯輸出如下:

入隊順序 1 ,2 ,3 ,4 ,5 , 隊列長度: 5 取出隊列一個數據:1 取出隊列一個數據:2 隊列長度: 3 銷毀隊列 大小固定的隊列測試 入隊順序 10 ,11 ,12 ,13 ,14 ,15 , 隊列已滿 取出隊列一個數據:10 取出隊列一個數據:11 隊列未滿 隊列長度是:4 銷毀隊列 隊列已空

輸出完全正確。

編輯:jq

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 數據
    +關注

    關注

    8

    文章

    7102

    瀏覽量

    89281
  • 函數
    +關注

    關注

    3

    文章

    4341

    瀏覽量

    62800

原文標題:數據結構與算法篇-隊列

文章出處:【微信號:AndroidPush,微信公眾號:Android編程精選】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    JavaWeb消息隊列使用指南

    在現代的JavaWeb應用中,消息隊列(Message Queue)是一種常見的技術,用于異步處理任務、解耦系統組件、提高系統性能和可靠性。 1. 消息隊列的基本概念 消息隊列是一種應用程序對應
    的頭像 發表于 11-25 09:27 ?172次閱讀

    探索字節隊列的魔法:多類型支持、函數重載與線程安全

    數據結構,它能夠高效地存儲和管理數據流。通過使用字節隊列,我們可以靈活地處理不同類型的數據、確保數據的完整性,并在多線程環境中安全地進行操
    的頭像 發表于 11-15 01:08 ?838次閱讀
    探索字節<b class='flag-5'>隊列</b>的魔法:多類型支持、函數重載與線程安全

    為什么同一個隊列引用的全局變量,運行在兩個子vi中發現隊列數據丟失了

    我創建了一個隊列,然后將隊列引用做了個全局變量,運行在兩個子vi中,一個是只入隊列,另一個是只出隊列。但我發現,一個字vi數據
    發表于 11-14 11:47

    視覺軟件HALCON的數據結構

    在研究機器視覺算法之前,我們需要先了解機器視覺應用中涉及的基本數據結構。Halcon數據結構主要有圖像參數和控制參數兩類參數。圖像參數包括:image、region、XLD,控制參數包括:string、integer、real、
    的頭像 發表于 11-14 10:20 ?476次閱讀
    視覺軟件HALCON的<b class='flag-5'>數據結構</b>

    嵌入式環形隊列與消息隊列實現原理

    嵌入式環形隊列,也稱為環形緩沖區或循環隊列,是一種先進先出(FIFO)的數據結構,用于在固定大小的存儲區域中高效地存儲和訪問
    的頭像 發表于 09-02 15:29 ?605次閱讀

    玩轉RT-Thread消息隊列的應用

    不同來源的數據,確保系統的穩定性和響應速度。一、設計消息結構二、創建消息隊列在service.c文件中,我們需要創建一個消息隊列來存放這些消息,并在處理線程中接收和
    的頭像 發表于 07-23 08:11 ?637次閱讀
    玩轉RT-Thread<b class='flag-5'>之</b>消息<b class='flag-5'>隊列</b>的應用

    嵌入式實時操作系統中的隊列管理與應用

    任務 A 將信息存入隊列,任務B以先進先出的方式提取信息。隊列通常應足夠大,可以承載許多數據,而不僅僅承載單個數據項。因此,它可以充當緩沖或暫存器,為管道提供靈活性。
    發表于 04-30 14:27 ?634次閱讀
    嵌入式實時操作系統中的<b class='flag-5'>隊列</b>管理與應用

    Freertos隊列項里的字節長度是否可以獲取?

    最近剛學Freertos, 看到可以獲取Freertos隊列長度,但是隊列項里的字節長度是否可以獲取? 因為項目中隊列中會存放不定長字節,需要對隊列中的
    發表于 04-29 07:17

    OpenHarmony語言基礎類庫【@ohos.util.Queue (線性容器Queue)】

    Queue的特點是先進先出,在尾部增加元素,在頭部刪除元素。根據循環隊列數據結構實現
    的頭像 發表于 04-27 21:20 ?350次閱讀
    OpenHarmony語言基礎類庫【@ohos.util.Queue (線性容器Queue)】

    用FreeRTOS使用隊列怎么發送一個結構體呢?

    怎么使用隊列,發送一個12個字節的結構體呢? osEvent osMessageGet (osMessageQId queue_id, uint32_t millisec
    發表于 04-17 07:35

    進程間通信的消息隊列介紹

    消息隊列是一種非常常見的進程間通信方式。
    的頭像 發表于 04-08 17:27 ?325次閱讀

    MCU專屬隊列功能模塊QueueForMcu應用

    當需要從隊列頭部獲取多個數據,但又不希望數據隊列中刪除時,可以使用 Queue_Peek_Array 函數來實現,該函數的參數與返回值與
    發表于 03-20 11:44 ?533次閱讀
    MCU專屬<b class='flag-5'>隊列</b>功能模塊<b class='flag-5'>之</b>QueueForMcu應用

    TC399 adc能添加到同一個隊列中并得到結果嗎?加入隊列是否有任何限制?

    你好,,我正在嘗試實現 ADC。 在我的項目中,我們使用 AN0...AN60 進行不同的電壓監控。 從數據表中可以發現,這些是不同的通道和組。 在一個示例程序中,它顯示將第 0 組的 3 個通道
    發表于 03-04 06:33

    矢量與柵格數據結構各有什么特征

    數據結構是使用點、線和面等基本幾何圖形來描述和表示地理對象的一種方法。它們由離散的幾何對象和與相關的屬性數據組成。矢量數據中的點表示一個特定的地理位置,線表示兩個或多個點之間的連接,
    的頭像 發表于 02-25 15:06 ?2719次閱讀

    裸機中環形隊列與RTOS中消息隊列有何區別呢?

    環形隊列”和“消息隊列”在嵌入式領域有應用非常廣泛,相信有經驗的嵌入式軟件工程師對它們都不陌生。
    的頭像 發表于 01-26 09:38 ?735次閱讀
    裸機中<b class='flag-5'>環形</b><b class='flag-5'>隊列</b>與RTOS中消息<b class='flag-5'>隊列</b>有何區別呢?
    主站蜘蛛池模板: 中国美女毛片| 亚洲人成伊人成综合网久久| 欧美成人午夜片一一在线观看| 亚洲福利秒拍一区二区| 在线午夜影院| 中文在线免费看影视| 午夜影院网站| 手机看片福利盒子| 国产大片免费观看资源| 天天干天天舔| 俺去操| 97伊人| 天天操夜夜艹| 国产精品色片| 久久久精品2021免费观看| 国产男人午夜视频在线观看| 欧美性猛交xxxx乱大交| 免费观看做网站爱| 色黄视频| 正在播放淫亚洲| 手机天堂网| 在线亚洲成人| 色综合中文网| 黄网站色成年片大免费软件| 欧美黄色一级片视频| 色丁香在线观看| 六月丁香六月婷婷| 美女毛片免费| 99pao在线视频精品免费| 天天搞夜夜| 欧美18性欧美丶黑吊| 在线你懂得| 欧美视频精品在线| 免费毛片网站在线观看| 国产美女在线观看| 国产馆精品推荐在线观看| 午夜特级毛片| a看片| 伊人一区二区三区| 麦克斯奥特曼在线观看| 五月天婷婷在线免费观看|