七、隊列————相關概念詳解

隊列————相關概念詳解

  • 前言
  • 一、隊列
    • 1.1 隊列是什么?
    • 1.2 隊列的類比
  • 二、隊列的常用操作
  • 三、隊列的實現
    • 3.1 基于數組實現隊列
      • 3.1.1 基于環形數組實現的隊列
      • 3.1.2 基于動態數組實現的隊列
    • 3.2 基于鏈表實現隊列
  • 四、隊列的典型應用
  • 總結


前言

  • 本篇文章,我們一起來學習隊列的知識。

一、隊列

1.1 隊列是什么?

  • 隊列(queue)是一種遵循先入先出規則的線性數據結構。
  • 在這里插入圖片描述

1.2 隊列的類比

  • 顧名思義,隊列模擬了排隊現象,即新來的人不斷加入隊列尾部,而位于隊列頭部的人逐個離開。

二、隊列的常用操作

  • 隊列的操作效率
方法名描述時間復雜度
push()元素入隊,即將元素添加至隊尾 O ( 1 ) O(1) O(1)
pop()隊首元素出隊 O ( 1 ) O(1) O(1)
peek()訪問隊首元素 O ( 1 ) O(1) O(1)
  • 實際上 python 中有寫好的 隊列的類, 我們可以直接使用隊列的包

代碼演示:

from collections import deque# 初始化隊列
# 在 Python 中,我們一般將雙向隊列類 deque 當作隊列使用
# 雖然 queue.Queue() 是純正的隊列類,但不太好用,因此不推薦
que: deque[int] = deque()# 元素入隊
que.append(1)
que.append(3)
que.append(2)
que.append(5)
que.append(4)# 訪問隊首元素
front: int = que[0]# 元素出隊
pop: int = que.popleft()# 獲取隊列的長度
size: int = len(que)# 判斷隊列是否為空
is_empty: bool = len(que) == 0

三、隊列的實現

  • 為了實現隊列,我們需要一種數據結構,可以在一端添加元素,并在另一端刪除元素,鏈表和數組都符合要求

3.1 基于數組實現隊列

  • 我們可以數組的第一個元素當成隊頭,每次入隊的時候,相當于是在添加數組,出隊的時候,我們返回數組的第一個元素,并將其從數組中刪除。
  • 但是在數組中刪除首元素的時間復雜度為 O ( n ) O(n) O(n),這會導致出隊操作效率較低。然而,我們可以采用以下巧妙方法來避免這個問題。
    • 我們可以使用一個變量 front 指向隊首元素的索引,并維護一個變量 size 用于記錄隊列長度。定義 rear = front + size ,這個公式計算出的 rear 指向隊尾元素之后的下一個位置。

3.1.1 基于環形數組實現的隊列

  • 在不斷進行入隊和出隊的過程中,front 和 rear 都在向右移動,當它們到達數組尾部時就無法繼續移動了。為了解決此問題,我們可以將數組視為首尾相接的“環形數組”。
  • 對于環形數組,我們需要讓 front 或 rear 在越過數組尾部時,直接回到數組頭部繼續遍歷。這種周期性規律可以通過“取余操作”來實現,代碼如下所示:

代碼演示:

class ArrayQueue:"""基于環形數組實現的隊列"""def __init__(self, size: int):"""構造方法"""self._nums: list[int] = [0] * size  # 用于存儲隊列元素的數組self._front: int = 0  # 隊首指針,指向隊首元素self._size: int = 0  # 隊列長度def capacity(self) -> int:"""獲取隊列的容量"""return len(self._nums)def size(self) -> int:"""獲取隊列的長度"""return self._sizedef is_empty(self) -> bool:"""判斷隊列是否為空"""return self._size == 0def push(self, num: int):"""入隊"""if self._size == self.capacity():raise IndexError("隊列已滿")# 計算隊尾指針,指向隊尾索引 + 1# 通過取余操作實現 rear 越過數組尾部后回到頭部rear: int = (self._front + self._size) % self.capacity()# 將 num 添加至隊尾self._nums[rear] = numself._size += 1def pop(self) -> int:"""出隊"""num: int = self.peek()# 隊首指針向后移動一位,若越過尾部,則返回到數組頭部self._front = (self._front + 1) % self.capacity()self._size -= 1return numdef peek(self) -> int:"""訪問隊首元素"""if self.is_empty():raise IndexError("隊列為空")return self._nums[self._front]def to_list(self) -> list[int]:"""返回列表用于打印"""res = [0] * self.size()j: int = self._frontfor i in range(self.size()):res[i] = self._nums[(j % self.capacity())]j += 1return res

3.1.2 基于動態數組實現的隊列

  • 3.1.2 實現的隊列仍然具有局限性:其長度不可變。
  • 然而,這個問題不難解決,我們可以將數組替換為動態數組,從而引入擴容機制。

代碼演示:

class DynamicArrayQueue:"""基于動態數組實現的隊列"""def __init__(self):"""構造方法"""self._nums: list[int] = []  # 動態數組用于存儲隊列元素self._front: int = 0  # 隊首指針def size(self) -> int:"""獲取隊列的長度"""return len(self._nums) - self._frontdef is_empty(self) -> bool:"""判斷隊列是否為空"""return self.size() == 0def push(self, num: int):"""入隊"""self._nums.append(num)  # 直接添加到列表尾部def pop(self) -> int:"""出隊"""if self.is_empty():raise IndexError("隊列為空")num: int = self.peek()self._front += 1  # 增加隊首指針# 清理不再使用的空間(可選)if self._front > len(self._nums) // 2:  # 如果已移除的元素超過一半self._resize()  # 縮減隊列的內部數組return numdef peek(self) -> int:"""訪問隊首元素"""if self.is_empty():raise IndexError("隊列為空")return self._nums[self._front]def _resize(self):"""縮減隊列的內部數組"""self._nums = self._nums[self._front:]  # 創建新列表,只包含有效元素self._front = 0  # 重置front指針def to_list(self) -> list[int]:"""返回列表用于打印"""return self._nums[self._front:]  # 返回從當前front開始的有效元素# 使用隊列
dq = DynamicArrayQueue()
dq.push(1)
dq.push(2)
print(dq.pop())  # 輸出: 1
dq.push(3)
print(dq.to_list())  # 輸出: [2, 3]

3.2 基于鏈表實現隊列

  • 我們可以將鏈表的“頭節點”和“尾節點”分別視為“隊首”和“隊尾”,規定隊尾僅可添加節點,隊首僅可刪除節點。

代碼演示:

class LinkedListQueue:"""基于鏈表實現的隊列"""def __init__(self):"""構造方法"""self._front: ListNode | None = None  # 頭節點 frontself._rear: ListNode | None = None  # 尾節點 rearself._size: int = 0def size(self) -> int:"""獲取隊列的長度"""return self._sizedef is_empty(self) -> bool:"""判斷隊列是否為空"""return self._size == 0def push(self, num: int):"""入隊"""# 在尾節點后添加 numnode = ListNode(num)# 如果隊列為空,則令頭、尾節點都指向該節點if self._front is None:self._front = nodeself._rear = node# 如果隊列不為空,則將該節點添加到尾節點后else:self._rear.next = nodeself._rear = nodeself._size += 1def pop(self) -> int:"""出隊"""num = self.peek()# 刪除頭節點self._front = self._front.nextself._size -= 1return numdef peek(self) -> int:"""訪問隊首元素"""if self.is_empty():raise IndexError("隊列為空")return self._front.valdef to_list(self) -> list[int]:"""轉化為列表用于打印"""queue = []temp = self._frontwhile temp:queue.append(temp.val)temp = temp.nextreturn queue

四、隊列的典型應用

  • 淘寶訂單。購物者下單后,訂單將加入隊列中,系統隨后會根據順序處理隊列中的訂單。在雙十一期間,短時間內會產生海量訂單,高并發成為工程師們需要重點攻克的問題。
  • 各類待辦事項。任何需要實現“先來后到”功能的場景,例如打印機的任務隊列、餐廳的出餐隊列等,隊列在這些場景中可以有效地維護處理順序。

總結

  • 文章介紹了隊列的實現方式,還有其常用函數,最后我們基于數組還有鏈表實現了隊列。

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

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

相關文章

基于 Ragflow 搭建知識庫-初步實踐

基于 Ragflow 搭建知識庫-初步實踐 一、簡介 Ragflow 是一個強大的工具,可用于構建知識庫,實現高效的知識檢索和查詢功能。本文介紹如何利用 Ragflow 搭建知識庫,包括環境準備、安裝步驟、配置過程以及基本使用方法。 二、環境準備 硬件要…

Pandas03

Pandas01 Pandas02 文章目錄 內容回顧1 排序和統計函數2 缺失值處理2.1 認識缺失值2.2 缺失值處理- 刪除2.3 缺失值處理- 填充非時序數據時序數據 3 Pandas數據類型3.1 數值類型和字符串類型之間的轉換3.2 日期時間類型3.3 日期時間索引 4 分組聚合4.1 分組聚合的API使用4.2 分…

springboot整合log4j2日志框架1

一 log4j基本知識 1.1 log4j的日志級別 Log4j定義了8個級別的log(除去OFF和ALL,可以說分為6個級別),優先級從低到高依次為:All,trace,debug,info,warn,err…

Spring源碼_05_IOC容器啟動細節

前面幾章,大致講了Spring的IOC容器的大致過程和原理,以及重要的容器和beanFactory的繼承關系,為后續這些細節挖掘提供一點理解基礎。掌握總體脈絡是必要的,接下來的每一章都是從總體脈絡中, 去研究之前沒看的一些重要…

WPF使用OpenCvSharp4

WPF使用OpenCvSharp4 創建項目安裝OpenCvSharp4 創建項目 安裝OpenCvSharp4 在解決方案資源管理器中,右鍵單擊項目名稱,選擇“管理 NuGet 包”。搜索并安裝以下包: OpenCvSharp4OpenCvSharp4.ExtensionsOpenCvSharp4.runtime.winSystem.Man…

leetcode 3083. 字符串及其反轉中是否存在同一子字符串 簡單

給你一個字符串 s ,請你判斷字符串 s 是否存在一個長度為 2 的子字符串,在其反轉后的字符串中也出現。 如果存在這樣的子字符串,返回 true;如果不存在,返回 false 。 示例 1: 輸入:s "…

TCP-UDP調試工具推薦:Socket通信測試教程(附詳細圖解)

前言 在網絡編程與應用開發中,調試始終是一項不可忽視的重要環節。尤其是在涉及TCP/IP、UDP等底層網絡通信協議時,如何確保數據能夠準確無誤地在不同節點間傳輸,是許多開發者關注的核心問題。 調試的難點不僅在于定位連接建立、數據流控制及…

Vue.js框架:在線教育系統的安全性與穩定性

2.1系統開發使用的關鍵技術 本系統在開發中選擇B/S框架進行設計,語言采用Java,數據庫采用Mysql,并在設計中加入VUE.js技術,本系統的運行環境為Idea。 2.2 VUE.js技術介紹 VUE.js是一個用來開發前臺界面的JavaScript框架&#xff0…

【新方法】通過清華鏡像源加速 PyTorch GPU 2.5安裝及 CUDA 版本選擇指南

下面詳細介紹所提到的兩條命令,它們的作用及如何在你的 Python 環境中加速 PyTorch 等庫的安裝。 1. 設置清華鏡像源 pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple這條命令的作用是將 pip (Python 的包管理工具&#xf…

【數據結構】單鏈表的使用

單鏈表的使用 1、基本概念2、鏈表的分類3、鏈表的基本操作a、單鏈表節點設計b、單鏈表初始化c、單鏈表增刪節點**節點頭插:****節點尾插:****新節點插入指定節點后:**節點刪除: d、單鏈表修改節點e、單鏈表遍歷,并打印…

虛幻引擎是什么?

Unreal Engine,是一款由Epic Games開發的游戲引擎。該引擎主要是為了開發第一人稱射擊游戲而設計,但現在已經被成功地應用于開發模擬游戲、恐怖游戲、角色扮演游戲等多種不同類型的游戲。虛幻引擎除了被用于開發游戲,現在也用于電影的虛擬制片…

Linux(Centos 7.6)yum源配置

yum是rpm包的管理工具,可以自動安裝、升級、刪除軟件包的功能,可以自動解決軟件包之間的依賴關系,使得用戶更方便軟件包的管理。要使用yum必須要進行配置,個人將其分為三類,本地yum源、局域網yum源、第三方yum源&#…

Linux上更新jar包里的某個class文件

目標:替換voice-1.0.jar里的TrackHandler.class文件 一.查詢jar包里TrackHandler.class所在的路徑 jar -tvf voice-1.0.jar |grep TrackHandler 二.解壓出TrackHandler.class文件 jar -xvf voice-1.0.jar BOOT-INF/classes/com/yf/rj/handler/TrackHandler.cla…

機器學習中回歸預測模型中常用四個評價指標MBE、MAE、RMSE、R2解釋

在機器學習中,評估模型性能時常用的四個指標包括平均絕對誤差(Mean Absolute Error, MAE)、均方誤差(Mean Squared Error, MSE)、均方根誤差(Root Mean Squared Error, RMSE)和決定系數&#xf…

基于SpringBoot的Jwt認證以及密碼aes加密解密技術

目錄 前言 1.SpringBoot項目的創建 2.相關技術 3.項目架構 4.項目關鍵代碼 5.項目最終的運行效果 ?編輯 6.PostMan測試接口結果 前言 學習了SpringBoot之后,才覺得SpringBoot真的很方便,相比傳統的SSH,SSM,SpringBo…

uniapp下載打開實現方案,支持安卓ios和h5,下載文件到指定目錄,安卓文件管理內可查看到

uniapp下載&打開實現方案,支持安卓ios和h5 Android: 1、申請本地存儲讀寫權限 2、創建文件夾(文件夾不存在即創建) 3、下載文件 ios: 1、下載文件 2、保存到本地,需要打開文件點擊儲存 使用方法&…

77、將adaface的mtcnn模型npy文件轉成atlas310p模型,并進行推理

基本思想:將adaface的mtcnn模型npy文件轉成atlas310p模型進行推理。同時比對結果 ubuntu@ubuntu:~$ git clone https://github.com/mk-minchul/AdaFace.git Cloning into AdaFace... remote: Enumerating objects: 236, done. remote: Counting objects: 100% (109/109), don…

Spark SQL DML語句

【圖書介紹】《Spark SQL大數據分析快速上手》-CSDN博客 《Spark SQL大數據分析快速上手》【摘要 書評 試讀】- 京東圖書 Spark本地模式安裝_spark3.2.2本地模式安裝-CSDN博客 DML(Data Manipulation Language,數據操作語言)操作主要用來對…

農歷節日倒計時:基于Python的公歷與農歷日期轉換及節日查詢小程序

農歷節日倒計時:基于Python的公歷與農歷日期轉換及節日查詢小程序 摘要 又是一年春節即將到來,突然想基于Python編寫一個農歷節日的倒計時小程序。該程序能夠根據用戶輸入的農歷節日名稱,計算出距離該節日還有多少天。通過使用lunardate庫進…

線性直流電流

電阻網絡的等效 等效是指被化簡的電阻網絡與等效電阻具有相同的 u-i 關系 (即端口方程),從而用等效電阻代替電阻網絡之后,不 改變其余部分的電壓和電流。 串聯等效: 并聯等效: 星角變換 若這兩個三端網絡是等效的,從任…