數據結構·一篇搞定隊列!

hello,大家好啊,肖恩又拖更了,你們聽我狡辯,前段時間有期中考試,so我就沒什么時間寫這個,在這給大家道個歉😭😭😭
請添加圖片描述
我后面一定盡力不拖更
那么接下來,我們來看隊列這個數據結構

引言

隊列是另一種常見的數據結構,它遵循"先進先出"(FIFO)的原則。隊列通常用于存儲等待處理的任務或數據,如任務調度、資源分配等。了解隊列的基本概念和實現方式對于掌握算法和數據結構同樣很重要。

隊列的概念及結構

隊列:只允許在一端進行插入數據操作,在另一端進行刪除數據操作的特殊線性表,隊列具有先進先出
FIFO(First In First Out) 入隊列:進行插入操作的一端稱為隊尾 出隊列:進行刪除操作的一端稱為隊頭
在這里插入圖片描述

隊列的實現

隊列也可以數組和鏈表的結構實現,使用鏈表的結構實現更優一些,因為如果使用數組的結構,出隊列在數
組頭上出數據,效率會比較低。
那我們下面來實現隊列的一些操作
因為也不是很難,我直接附上代碼

#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#include<assert.h>typedef int QDataType;typedef struct QueueNode
{struct QueueNode* next;QDataType val;
}QNode;typedef struct Queue
{QNode* phead;QNode* ptail;int size;
}Queue;
//初始化
void QueueInit(Queue* pq) {assert(pq);pq->phead = pq->ptail = NULL;pq->size = 0;
}
//銷毀
void QueueDestroy(Queue* pq) {assert(pq);QNode* cur = pq->phead;while (cur) {QNode* next = cur->next;free(cur);cur = next;}pq->phead = pq->ptail == NULL;pq->size = 0;
}// 隊尾插入
void QueuePush(Queue* pq, QDataType x) {assert(pq);QNode* newnode = (QNode*)malloc(sizeof(QNode));if (newnode == NULL){perror("malloc fail");return;
}newnode->next = NULL;newnode->val = x;if (pq->phead == NULL)pq->phead = pq->ptail = newnode;elsepq->ptail->next = newnode;pq->ptail = newnode;pq->size++;
}
// 隊頭刪除
void QueuePop(Queue* pq) {assert(pq);assert(pq->size != 0);if (pq->phead->next = NULL) {free(pq->phead);pq->phead = pq->ptail = NULL;}else {QNode* next = pq->phead->next;free(pq->phead);pq->phead = next;}pq->size--;
}// 取隊頭和隊尾的數據
QDataType QueueFront(Queue* pq) {assert(pq && pq->phead);return pq->phead->val;
}QDataType QueueBack(Queue* pq) {assert(pq && pq->ptail);return pq->ptail->val;
}
// 獲取隊列中有效元素個數
int QueueSize(Queue* pq) {assert(pq);return pq->size;
}
// 檢測隊列是否為空
bool QueueEmpty(Queue* pq) {assert(pq);return pq->size == 0;
}

簡單說兩個主要的操作

  1. 隊尾插入 (QueuePush):

    • 首先檢查傳入的隊列指針是否為空,如果為空則拋出錯誤。
    • 分配一個新的節點內存空間。
    • 將新節點的 next 指針設置為 NULL,并將待插入的數據 x 存儲到節點的 val 字段。
    • 如果隊列為空,則將新節點同時設置為頭指針 phead 和尾指針 ptail
    • 否則,將當前尾節點的 next 指針指向新節點,并更新尾指針 ptail 指向新節點。
    • 最后將隊列大小 size 加 1。
  2. 隊頭刪除 (QueuePop):

    • 首先檢查傳入的隊列指針是否為空,如果為空則拋出錯誤。
    • 檢查隊列是否為空,如果為空則什么也不做直接返回。
    • 如果隊列只有一個節點,則釋放該節點并將頭尾指針都設置為 NULL
    • 否則,獲取頭節點的下一個節點,釋放頭節點,并將頭指針 phead 指向下一個節點。
    • 最后將隊列大小 size 減 1。

通過這兩個基本操作,我們可以實現一個基于鏈表的隊列數據結構,支持向隊列尾部添加元素和從隊列頭部刪除元素的功能。

實際中我們有時還會使用一種隊列叫循環隊列。環形隊列可以使用數組實現,也可以使用循環鏈表實現。
使用循環隊列的優點是可以高效地利用數組空間,避免了普通隊列在刪除元素時,需要移動所有剩余元素的問題。但同時也需要額外維護頭尾指針,增加了一定的復雜度。

循環隊列在某些場景下,如緩存管理、生產者-消費者模型等,能夠發揮出較好的性能表現。
那么下面的一個面試題(也是考研題)就讓我們來看看循環隊列。

例題

設計循環隊列
在這里插入圖片描述

使用動態數組很方便
我相信下面詳細的注釋能讓你明白循環隊列是怎么回事,不是很理解的話,可以自己畫圖來便于理解

// 定義循環隊列結構體
typedef struct {int *a;  // 存儲隊列元素的動態數組int head; // 隊頭下標int tail; // 隊尾下標int k;    // 隊列最大容量
} MyCircularQueue;// 檢查隊列是否為空
bool myCircularQueueIsEmpty(MyCircularQueue *obj) {return obj->head == obj->tail; // 當 head 和 tail 相等時,隊列為空
}// 檢查隊列是否已滿
bool myCircularQueueIsFull(MyCircularQueue *obj) {return (obj->tail + 1) % (obj->k + 1) == obj->head; // 當 (tail + 1) % (k + 1) 等于 head 時,隊列已滿
}// 創建一個容量為 k 的循環隊列
MyCircularQueue *myCircularQueueCreate(int k) {MyCircularQueue *p = (MyCircularQueue *)malloc(sizeof(MyCircularQueue)); // 分配 MyCircularQueue 結構體的內存p->a = (int *)malloc((k + 1) * sizeof(int));    // 分配存儲元素的動態數組p->k = k;                   // 設置隊列最大容量p->head = p->tail = 0;  // 初始化 head 和 tail 為 0return p;
}// 向隊列中添加一個元素
bool myCircularQueueEnQueue(MyCircularQueue *obj, int value) {if (myCircularQueueIsFull(obj))  // 如果隊列已滿,返回 falsereturn false;obj->a[obj->tail] = value;  // 將元素添加到隊尾obj->tail = (obj->tail + 1) % (obj->k + 1); // 更新 tail 下標,實現循環return true;}// 從隊列中刪除一個元素
bool myCircularQueueDeQueue(MyCircularQueue *obj) {if (myCircularQueueIsEmpty(obj)) { // 如果隊列為空,返回 falsereturn false;} else {obj->head = (obj->head + 1) % (obj->k + 1); // 更新 head 下標,實現刪除隊頭元素return true;}
}// 獲取隊頭元素
int myCircularQueueFront(MyCircularQueue *obj) {if (obj->tail == obj->head) { // 如果隊列為空,返回 -1return -1;} else {return obj->a[obj->head]; // 返回隊頭元素}
}// 獲取隊尾元素
int myCircularQueueRear(MyCircularQueue *obj) {if (obj->tail == obj->head) { // 如果隊列為空,返回 -1return -1;} else {return obj->a[(obj->tail + obj->k) % (obj->k + 1)]; // 返回隊尾元素}
}// 釋放循環隊列占用的內存空間
void myCircularQueueFree(MyCircularQueue *obj) {free(obj->a); // 釋放存儲元素的動態數組free(obj);     // 釋放 MyCircularQueue 結構體
}

循環隊列的存儲空間為 Q(1:100) ,初始狀態為 front=rear=100 。經過一系列正常的入隊與退隊操作
后, front=rear=99 ,則循環隊列中的元素個數為( )
A. 1
B. 2
C. 99
D. 0或者100

現有一循環隊列,其隊頭指針為front,隊尾指針為rear;循環隊列長度為N。其隊內有效長度為?(假設
隊頭不存放數據)
A. (rear - front + N) % N + 1
B. (rear - front + N) % N
C. (rear - front) % (N + 1)
D. (rear - front + N) % (N - 1)

解析:
在循環隊列中,隊頭指針 front 指向隊首元素的下一個位置(如果隊頭不存放數據),而隊尾指針 rear 指向隊尾元素的下一個位置。這意味著當隊列為空時,front 和 rear 通常指向同一個位置(或者在某些實現中,rear 可能在 front 的下一個位置,具體取決于如何定義“空”狀態)。

隊列的有效長度(即隊列中元素的數量)可以通過計算 rear 和 front 之間的差值來得到,但是需要注意這是一個循環結構,所以差值需要用模運算 % N 來處理。

假設 front 和 rear 的初始值都是 0(隊列為空),并且每次入隊操作 rear 會遞增,每次出隊操作 front 會遞增,那么隊列的有效長度可以用以下公式計算:

(rear - front + N) % N
這里加 N 是為了確保在 rear 小于 front 的情況下(即隊列繞了一圈之后),差值仍然是正數。然后取模 N 來得到一個 0 到 N-1 之間的值,這個值就是隊列的有效長度。

注意:這個公式假設 front 和 rear 的初始值都是 0,并且每次操作后都會遞增。如果初始值不是 0,或者有其他特殊的入隊/出隊邏輯,那么可能需要調整這個公式。
那么到這里,基本上隊列的東西都講完啦
在這里插入圖片描述
下一篇講隊列和棧的相互實現~~~
待會兒見
請添加圖片描述

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/15882.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/15882.shtml
英文地址,請注明出處:http://en.pswp.cn/web/15882.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Greenplum使用hbase外部表

概述 GP可以通過pxf協議上的hbase外表功能&#xff0c; 在數據庫中創建外部表&#xff0c;映射hbase table&#xff0c;以直接在gp中訪問 hbase數據&#xff0c;方便將hbase的查詢結果集保留在gp中 hbase端準備 HBase基礎概念&#xff1a; ?HBase 列包含兩個組件&#xff1…

粒子輻照環境中相機鏡頭防護及LabVIEW圖像處理注意事項

在粒子輻照環境測試電路板性能的實驗中&#xff0c;需要對相機鏡頭進行有效防護&#xff0c;同時利用LabVIEW進行圖像識別和處理。本文將討論相機鏡頭防護的關鍵因素和LabVIEW處理過程中的注意事項&#xff0c;包括防輻射材料選擇、輻射屏蔽措施、散熱管理、空間布局及LabVIEW軟…

c++11:左值引用和右值引用《全家桶》

總結一下C11中涉及到左值引用和右值引用的場景。 1 左值引用和右值引用的區別 左值引用 定義&#xff1a;對左值的引用。目的是避免內存拷貝&#xff0c;類似c中的指針,兩個場景&#xff1a;函數傳參、函數返回值。 右值引用 定義&#xff1a;對右值的引用。兩個場景&#…

【機器學習-k近鄰算法-01】 | Scikit-Learn工具包進階指南:機器學習sklearn.neighbors模塊之k近鄰算法實戰

&#x1f3a9; 歡迎來到技術探索的奇幻世界&#x1f468;?&#x1f4bb; &#x1f4dc; 個人主頁&#xff1a;一倫明悅-CSDN博客 ?&#x1f3fb; 作者簡介&#xff1a; C軟件開發、Python機器學習愛好者 &#x1f5e3;? 互動與支持&#xff1a;&#x1f4ac;評論 &…

騎行 - 新區永旺出發的環太湖路線

環過好幾次太湖&#xff0c;但對路線都沒太在意&#xff0c;都是跟著別人走的。這次自己制定一個路書&#xff0c;方便下次自己一個人環太湖時使用。 開始是使用高德地圖做路書&#xff0c;只能在PC上做。我用的是網頁版&#xff0c;每次選點太麻煩了。要輸入地址搜索&#xff…

開源博客項目Blog .NET Core源碼學習(27:App.Hosting項目結構分析-15)

本文學習并分析App.Hosting項目中后臺管理頁面的角色管理頁面。 ??角色管理頁面用于顯示、檢索、新建、編輯、刪除角色數據同時支持按角色分配菜單權限&#xff0c;以便按角色控制后臺管理頁面的菜單訪問權限。角色管理頁面附帶一新建及編輯頁面&#xff0c;以支撐新建和編輯…

電纜廠可視化:提升生產透明度與運營效率

圖撲電纜廠可視化系統通過實時監控和數據分析&#xff0c;提高生產過程的透明度和可控性&#xff0c;優化資源配置和質量管理&#xff0c;顯著提升運營效率和產品質量。

啟動SpringBoot項目及解決端口占用問題(指令版)

打包SpringBoot 項目 需要將 SpringBoot 項目進行打包。可以使用 Maven 的快捷工具&#xff0c;或者在項目的 pom.xml 文件所在目錄執行以下命令&#xff1a; mvn clean package部署注意 Windows系統下&#xff0c;按照以下方式在cmd窗口以管理員身份允許使用命令啟動spring…

Flutter 中的 StatefulBuilder 小部件:全面指南

Flutter 中的 StatefulBuilder 小部件&#xff1a;全面指南 在Flutter中&#xff0c;StatefulBuilder是一個高效的小部件&#xff0c;它根據給定的構建函數來構建widget&#xff0c;并在組件樹中只對需要重新構建的部分進行更新。這使得它在性能優化方面非常有用&#xff0c;特…

電子電器架構 - AUTOSAR ON THE AIR

電子電器架構 - AUTOSAR ON THE AIR 我是穿拖鞋的漢子,魔都中堅持長期主義的汽車電子工程師。 老規矩,分享一段喜歡的文字,避免自己成為高知識低文化的工程師: 屏蔽力是信息過載時代一個人的特殊競爭力,任何消耗你的人和事,多看一眼都是你的不對。非必要不費力證明自己…

Mybase長久破解

1、軟件下載好之后&#xff0c;找到文件mybase8.ini文件 2、使用記事本打開&#xff0c;通過 Ctrl F 輸入快速找到屬性設置FirstUseOn.UserLic.App&#xff0c;將等號后面的數值刪掉保存即可 3、使用防護中心–>自定義防護&#xff08;記得開啟&#xff09; 4、添加規則…

Golang文件操作

文章目錄 文件操作基本介紹普通的文件操作方式&#xff08;os包&#xff09;帶緩沖的文件操作方式&#xff08;bufio包&#xff09;文件拷貝操作&#xff08;io包&#xff09; 命令行參數基本介紹解析命令行參數&#xff08;flag包&#xff09; JSON基本介紹JSON序列化JSON反序…

【MySQL精通之路】MySQL的使用(3)-連接到服務器的配置

目錄 1.連接建立的命令選項 1.1.--default-auth 1.2.--hosthost_name, -h host_name 1.3.--password[pass_val], -p[pass_val] 1.4.--password1[pass_val] 1.5.--password2[pass_val] 1.6.--password3[pass_val] 1.7.--pipe, -W 1.8.--plugin-dirdir_name 1.9.--port…

【YOLOv10訓練】:報錯 AttributeError: ‘str‘ object has no attribute ‘view‘ 解決方法

YOLOv10訓練報錯 YOLOv10是在YOLOv8基礎上修改的&#xff0c;即&#xff1a;訓練方法和過程是相同的。 但按照v8訓練程序train.py&#xff0c;如下所示&#xff0c;直接訓練&#xff1a; from ultralytics import YOLO# Load a model model YOLO("ultralytics/cfg/mod…

真拿AI賺到錢的人,不在朋友圈里

1 最近有張兩大AI巨頭對比的梗圖給我看樂了&#xff0c;玩兒AI的還在做產品&#xff0c;玩兒焦慮的已經在數錢了。 這也是在做AI&#xff0c;只不過是唉聲嘆氣的ai。 要我說&#xff0c;現在缺的根本不是AI&#xff0c;而是【有用的AI】。 恩格斯老師說過一句話&#xff1a…

科林Linux6_網絡

#include<sys/socket.h> #include<arpa/inet.h> //大小端轉換 #include<netdb.h> //DNS一、Socket套接字 為了開發網絡應用&#xff0c;系統提供一套API函數接口&#xff0c;用于網絡應用開發&#xff0c;這些接口稱為套接字函數 struct sockaddr_in…

數據庫管理-第194期 網絡加速RDMA初探(20240526)

數據庫管理194期 2024-05-26 數據庫管理-第194期 網絡加速RDMA初探&#xff08;20240526&#xff09;1 概念2 發展3 使用總結 數據庫管理-第194期 網絡加速RDMA初探&#xff08;20240526&#xff09; 作者&#xff1a;胖頭魚的魚缸&#xff08;尹海文&#xff09; Oracle ACE A…

英文 海量的學習句子比單獨的記單詞效果要好,格句致知。

英文 海量的學習句子比單獨的記單詞效果要好 句子有上下文、場景和時態等&#xff0c;能形成劇情&#xff0c;變得生動有趣。 如果一句沒聽懂&#xff0c;還繼續聽就是浪費時間了。要一句一句地深究&#xff0c;不然就要讀好幾遍&#xff0c;還得背誦。要深入理解&#xff0c…

不同的二叉搜索樹(II)題解

toc &#x1f91a;我的博客 歡迎光臨我的博客&#xff1a;https://blog.csdn.net/qq_52434217?typeblog &#x1f95b;前言 動態規劃是常見的算法思路&#xff0c;動態規劃在計算過程中保存了部分計算結果到內存中&#xff0c;以便于在進行下一次計算時可以直接從內存中獲…

Ubuntu部署Dolphinscheduler單機版并配置PG數據庫

1、下載并解壓Dolphinscheduler DolphinScheduler | 下載 (apache.org) 下載完成后得tar.gz包 下載穩定版 下載穩定版 下載穩定版 tar -zxvf apache-dolphinscheduler-3.1.9-alpha-bin.tar.gz mv apache-dolphinscheduler-3.1.9-alpha-bin dolphinscheduler-bin cd dolph…