【左程云算法07】隊列和棧-鏈表數組實現

目錄

?編輯1)隊列的介紹

核心操作

3)隊列的鏈表實現和數組實現

使用數組實現隊列

2)棧的介紹

核心操作

4)棧的數組實現

使用語言內置的實現

使用數組手動實現棧

5)環形隊列的實現 leecode622

代碼解析


視頻鏈接
【算法講解013【入門】隊列和棧-鏈表、數組實現】

1)隊列的介紹

先進先出。進了從尾進,從頭出。

隊列我們認為范圍是左閉右開的。范圍是[L,R),因此如果L<R,就說明有元素,如果L==R,說明隊列里沒有元素。

如果我們想加b到R位置,那么我們R++;(原來R在1位置)

如果我們想讓數彈出,那么我們拿L位置的數,讓L++

隊列是一種遵循?先進先出 (First-In, First-Out, FIFO)?原則的線性數據結構。

可以把它想象成現實生活中的排隊:最早來排隊的人,最先獲得服務并離開。在數據結構中,最早被放入(入隊)的元素,也最先被取出(出隊)。

核心操作

一個基本的隊列通常支持以下幾種操作:

  • offer(value)?(或?enqueue): 將一個元素添加到隊尾。

  • poll()?(或?dequeue): 從隊頭取出一個元素,并將其從隊列中移除。

  • peek()?(或?head): 查看隊頭的元素,但不移除它。

  • isEmpty(): 判斷隊列是否為空。

  • size():返回隊列中元素的個數。

3)隊列的鏈表實現和數組實現

在很多語言中,都有現成的、基于鏈表實現的隊列結構。例如在 Java 中,LinkedList?類就實現了?Queue?接口。

// 直接用Java內部的實現
// 其實內部就是雙向鏈表,常數操作
public static class Queue1 {// java中的雙向鏈表LinkedList就足夠了public Queue<Integer> queue = new LinkedList<>();// 調用任何方法之前,先調用這個方法來判斷隊內是否有東西public boolean isEmpty() {return queue.isEmpty();}// 向隊內加入num, 加到隊尾public void offer(int num) {queue.offer(num);}// 從隊頭拿,從頭拿public int poll() {return queue.poll();}
}

使用現成的?LinkedList?來實現隊列非常簡單,因為其雙向鏈表的結構天然支持在頭部和尾部進行 O(1) 復雜度的增刪操作,完美契合隊列的需求。

使用數組實現隊列

在筆試和面試中,更常見的要求是讓我們手動用數組來實現一個隊列。這更能考察我們對數據結構底層實現的理解。

這是一個基礎版的數組隊列實現:

// 實際刷題時更常見的寫法,常數時間好
// 如果可以確定加入操作的總次數不超過n,那么可以用
// 一般筆試、面試都會有一個明確數據量,所以這是最常用的方式
public static class Queue2 {public int[] queue;public int l; // 頭指針public int r; // 尾指針// 加入操作的總次數上限是多少,一定要明確public Queue2(int n) {queue = new int[n];l = 0;r = 0;}// 調用任何方法之前,先調用這個方法來判斷隊內是否有東西public boolean isEmpty() {return l == r;}// 入隊操作public void offer(int num) {queue[r++] = num;}// 出隊操作public int poll() {return queue[l++];}// 查看隊頭public int head() {return queue[l];}// 查看隊尾public int tail() {return queue[r - 1];}// 查看大小public int size() {return r - l;}
}

代碼解析

  • 結構:我們用一個固定大小的數組?queue?作為容器,并設置兩個指針:

    • l?(left): 指向隊頭。下一個要被?poll?的元素就是?queue[l]。

    • r?(right): 指向下一個可以插入元素的位置。下一個?offer?的元素將被放入?queue[r]。

  • isEmpty(): 當?l?和?r?指針相遇時 (l == r),說明隊列中沒有任何元素,隊列為空。

  • offer(num): 將元素?num?放入?r?指向的位置,然后將?r?指針后移 (r++)。

  • poll(): 返回?l?指向的元素,然后將?l?指針后移 (l++)。

這種實現的局限性
這個基礎版的數組隊列有一個明顯的問題:指針?l?和?r?只能單向地向右移動。這意味著,即使我們?poll?了很多元素,數組前面空出來的空間也無法被重新利用。當?r?到達數組末尾時,即使隊列實際大小很小,我們也無法再?offer?新的元素了。

2)棧的介紹

像彈匣一樣,裝的時候放在上一個的上面彈出的時候也是上面的先彈出。先d再c等等。

和上面的隊類似。

與隊列的“先進先出”相反,棧是一種遵循?后進先出 (Last-In, First-Out, LIFO)?原則的線性數據結構。

它最經典的類比就是一摞盤子:我們總是把新盤子放在最上面,而取盤子時,也總是從最上面拿。最后放上去的盤子,最先被取走。

核心操作

一個基本的棧通常支持以下幾種操作:

  • push(value): 將一個元素壓入棧頂。

  • pop(): 從棧頂彈出一個元素,并將其從棧中移除。

  • peek(): 查看棧頂的元素,但不移除它。

  • isEmpty(): 判斷棧是否為空。

  • size():返回棧中元素的個數。

4)棧的數組實現

使用語言內置的實現

Java 提供了?java.util.Stack?類,可以直接使用。它的底層是動態數組 (Vector)。

// 直接用Java內部的實現
// 其實就是動態數組,不過常數時間并不好
public static class Stack1 {public Stack<Integer> stack = new Stack<>();// 調用任何方法之前,先調用這個方法來判斷棧內是否有東西public boolean isEmpty() {return stack.isEmpty();}public void push(int num) {stack.push(num);}public int pop() {return stack.pop();}public int peek() {return stack.peek();}public int size() {return stack.size();}
}

使用數組手動實現棧

這是在筆試、面試中考察的重點。我們通過一個數組和一個指針(或索引)來模擬棧的行為。

// 實際刷題時更常見的寫法,常數時間好
// 如果可以保證同時在棧里的元素個數不超過n,那么可以用
// 也就是發生彈出操作之后,空間可以復用
// 一般筆試、面試都會有一個明確數據量,所以這是最常用的方式
public static class Stack2 {public int[] stack;public int size; // 指針,指向下一個可插入的位置// 同時在棧里的元素個數不超過npublic Stack2(int n) {stack = new int[n];size = 0;}// 調用任何方法之前,先調用這個方法來判斷棧內是否有東西public boolean isEmpty() {return size == 0;}// 入棧public void push(int num) {stack[size++] = num;}// 出棧public int pop() {return stack[--size];}// 查看棧頂元素public int peek() {return stack[size - 1];}// 返回棧中元素數量public int size() {return size;}
}

代碼解析

  • 結構:我們使用一個固定大小的數組?stack?和一個整型變量?size。這里的?size?非常巧妙,它既表示了棧中當前的元素數量,也同時扮演了棧頂指針的角色,指向下一個新元素應該被插入的位置。

  • isEmpty(): 當?size?為 0 時,棧為空。

  • push(num): 將新元素?num?放入?stack[size]?的位置,然后將?size?加一 (size++)。

  • pop(): 先將?size?減一 (--size),使其指向當前的棧頂元素,然后返回?stack[size]。注意,數據并沒有從數組中被“清除”,但它已經變得不可訪問,后續的?push?操作會覆蓋它。這就是“空間復用”的體現。

  • peek(): 直接返回?stack[size - 1]?的值,因為?size - 1?正是當前棧頂元素的索引。

這種數組實現方式,所有操作的平均時間復雜度都是 O(1),性能非常好。

5)環形隊列的實現 leecode622

舉個例子,一共有五個位置,abcd依次放進去,a位置是頭,d位置是尾,此時我想把a彈出,就像上文中的隊列彈出,空間釋放。頭往后去。我再彈出個b接著我再加個e呢?

我要是再加個f呢?

但注意,c位置是頭。

再加個g呢?

所以這就是個環形結構

所以只要你不同時多于5個在這個隊列里,就能一直保持著環形隊列繼續下去。

那怎么寫代碼呢?

前提:size允許才能做操作一和操作二

這道題limit就是5

我現在要加入a

我再加個b,再加個c

彈出a

再加個d呢

再彈出b

再加個e

再加個f 放到尾巴的位置,這不就復用了嗎?

https://leetcode.cn/problems/design-circular-queue/

// 設計循環隊列
// 測試鏈接 : https://leetcode.cn/problems/design-circular-queue/
class MyCircularQueue {public int[] queue;public int l; // 頭指針public int r; // 尾指針public int size; // 當前隊列大小public int limit; // 隊列容量// 構造器,設置隊列長度為 kpublic MyCircularQueue(int k) {queue = new int[k];l = r = size = 0;limit = k;}// 向循環隊列插入一個元素。如果成功插入則返回真public boolean enQueue(int value) {if (isFull()) {return false;} else {queue[r] = value;// r++, 結束了,跳回0r = r == limit - 1 ? 0 : (r + 1);size++;return true;}}// 從循環隊列中刪除一個元素。如果成功刪除則返回真public boolean deQueue() {if (isEmpty()) {return false;} else {// l++, 結束了,跳回0l = l == limit - 1 ? 0 : (l + 1);size--;return true;}}// 從隊首獲取元素。如果隊列為空,返回 -1public int Front() {if (isEmpty()) {return -1;} else {return queue[l];}}// 獲取隊尾元素。如果隊列為空,返回 -1public int Rear() {if (isEmpty()) {return -1;} else {// r 指向的是下一個要插入的位置,所以隊尾元素在 r 的前一個位置// 需要計算 r 的前一個位置,同樣要考慮循環int last = r == 0 ? (limit - 1) : (r - 1);return queue[last];}}// 檢查循環隊列是否為空public boolean isEmpty() {return size == 0;}// 檢查循環隊列是否已滿public boolean isFull() {return size == limit;}
}

代碼解析

  • 成員變量

    • l?和?r:與之前一樣,分別是頭指針和尾指針。

    • limit:數組的總容量,即隊列的容量上限。

    • size:核心變量。我們引入一個?size?變量來實時記錄隊列中元素的個數。這使得判斷隊列是“空”還是“滿”變得極其簡單,避免了復雜的指針位置判斷。

  • enQueue(value)?入隊

    1. 首先通過?isFull()?判斷隊列是否已滿。

    2. queue[r] = value;:在尾指針?r?的位置放入新元素。

    3. r = r == limit - 1 ? 0 : (r + 1);:環形邏輯的關鍵。更新尾指針?r。如果?r?已經到達數組的最后一個位置 (limit - 1),則下一步就讓它跳回到 0;否則,就正常?+1。

    4. size++:隊列大小加一。

  • deQueue()?出隊

    1. 首先通過?isEmpty()?判斷隊列是否為空。

    2. l = l == limit - 1 ? 0 : (l + 1);:環形邏輯的關鍵。更新頭指針?l。與?r?的邏輯完全相同,如果?l?到達末尾,就跳回 0。

    3. size--:隊列大小減一。

  • Front()?查看隊頭

    • 如果隊列不為空,隊頭元素就是?l?指針指向的位置?queue[l]。

  • Rear()?查看隊尾

    • 這是最需要注意的地方。因為?r?指向的是下一個將要插入的位置,所以真正的隊尾元素在?r?的前一個位置。

    • int last = r == 0 ? (limit - 1) : (r - 1);:計算?r?的前一個位置,同樣需要考慮環形。如果?r?當前在 0,那么它的前一個位置就是數組的末尾?limit - 1;否則,就是?r - 1。

    • 返回?queue[last]?即可。

  • isEmpty()?和?isFull()

    • 有了?size?變量,這兩個判斷變得無比清晰:size == 0?即為空,size == limit?即為滿。

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

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

相關文章

Docker 清理完整指南:釋放磁盤空間的最佳實踐

前言 隨著 Docker 使用時間的增長,系統中會積累大量的容器、鏡像、數據卷和構建緩存,占用大量磁盤空間。本文將詳細介紹如何有效清理 Docker 資源,釋放磁盤空間,保持系統整潔。 Docker 資源類型 Docker 主要占用磁盤空間的資源包括: 容器 (Containers):運行中和已停止…

零基礎快速了解掌握Linux防火墻-Iptables

一、 Iptables概述Iptables 是一個用戶空間程序&#xff0c;可以用于設置和管理 Linux 操作系統的內核級防火墻。它通過表、鏈和 規則組成&#xff0c;可以靈活地根據不同的需求進行配置。iptables 具有以下特點&#xff1a;Iptables 作為內核級別的防火墻&#xff0c;具有高效…

12公里無人機圖傳模組:從模糊到超高清的飛躍,抗干擾能力全面升級

在無人機行業飛速發展的今天&#xff0c;高清圖像傳輸已成為衡量無人機性能的重要標志之一。過去&#xff0c;無人機在長距離飛行時常常面臨信號衰減、圖像模糊&#xff0c;甚至數據丟失的問題&#xff0c;影響了用戶的體驗與應用效果。為了打破這一瓶頸&#xff0c;業內專家不…

從 “模板” 到 “場景”,用 C++ 磨透拓撲排序的實戰邏輯

文章目錄前言&#xff1a;《算法磨劍: 用C思考的藝術》 專欄《C&#xff1a;從代碼到機器》 專欄《Linux系統探幽&#xff1a;從入門到內核》 專欄正文&#xff1a;[B3644 【模板】拓撲排序 / 家譜樹](https://www.luogu.com.cn/problem/B3644)【解法】【參考代碼】[P2712 攝像…

盲盒抽卡機小程序:從0到1的蛻變之路

盲盒抽卡機小程序從概念提出到最終上線&#xff0c;經歷了從0到1的蛻變過程。這個過程充滿了挑戰與機遇&#xff0c;也凝聚了開發團隊的智慧和汗水。本文將分享盲盒抽卡機小程序的開發歷程&#xff0c;探討其背后的技術實現和市場策略。需求分析&#xff1a;明確目標用戶與市場…

分層-三層架構

文章目錄介紹代碼拆分Dao層server層controller層運行結果介紹 在我們進行程序設計以及程序開發時&#xff0c;盡可能讓每一個接口、類、方法的職責更單一些&#xff08;單一職責原則&#xff09;。 單一職責原則&#xff1a;一個類或一個方法&#xff0c;就只做一件事情&#…

Vue2 VS Vue3

vue3 是的&#xff0c;Vue 3 確實取消了基于 JavaScript 原型的 Vue 和 VueComponent 構造函數&#xff08;即你提到的 vm 和 vc&#xff09;&#xff0c;取而代之的是一種完全不同的、基于普通對象和代理&#xff08;Proxy&#xff09;的實例管理方式。 這是一個顛覆性的改變…

Vue3入門到實戰,最新版vue3+TypeScript前端開發教程,Vue3簡介,筆記02

筆記02 一、Vue3簡介 1.1、Vue3發布日期&#xff1a; 2020年9月18日 1.2、Vue3做了哪些升級&#xff1a; 1.2.1、性能的提升 官方發版地址&#xff1a;Release v3.0.0 One Piece vuejs/core 打包大小減少41%初次渲染快55%更新渲染快133%內容減少54% 1.2.2、源碼的優化…

.net core webapi/mvc阿里云服務器部署 - 錯誤解決

錯誤及解決方案缺少web.config配置HTTP 錯誤 500.19 - Internal Server Error檢查 IIS 配置1. 確保 .NET Core Hosting Bundle 已安裝2. 檢查 應用程序池 配置3. 檢查 IIS MIME 類型檢查文件權限1. 確保 IIS 用戶 有權限訪問網站目錄2. 檢查 web.config 文件權限啟用詳細錯誤日…

多輸入(input)多輸出(output)驗證

#作者&#xff1a;程宏斌 文章目錄前言Flb 1.9.4 INCLUDE配置測試測試方案測試配置文件測試命令Flb 3.0.2 INCLUDE配置測試測試方案測試配置文件啟動命令結論結論一&#xff1a;結論二&#xff1a;前言 需要設計并執行一組測試用例&#xff0c;這些測試用例將包括以子文件形式…

行業學習【電商】:垂直電商如何理解?以專業寵物平臺為例

聲明&#xff1a;以下部分內容含AI生成 “寵物等愛好者的專業平臺”指的是垂直電商的一個具體例子。 “垂直電商” 就是指不賣所有東西&#xff0c;只深耕某一個特定領域&#xff08;即“垂直”領域&#xff09;的電商平臺。 “寵物愛好者的專業平臺”就是這樣一個專門為養寵…

GPT(Generative Pre-trained Transformer)模型架構與損失函數介紹

目錄 一、核心架構&#xff1a;Transformer Decoder 1. 核心組件&#xff1a;僅解碼器&#xff08;Decoder-Only&#xff09;的堆疊 2. 輸入表示&#xff1a;Token 位置 3. 輸出 二、訓練過程&#xff1a;兩階段范式 階段一&#xff1a;預訓練&#xff08;Pre-training&…

GitHub 熱榜項目 - 日榜(2025-09-10)

GitHub 熱榜項目 - 日榜(2025-09-10) 生成于&#xff1a;2025-09-10 統計摘要 共發現熱門項目&#xff1a;15 個 榜單類型&#xff1a;日榜 本期熱點趨勢總結 本期GitHub熱榜呈現三大技術熱點&#xff1a;LLM智能體應用爆發&#xff08;如parlant、AutoAgent&#xff09;&a…

論文閱讀:arxiv 2023 Large Language Models are Not Stable Recommender Systems

總目錄 大模型相關研究&#xff1a;https://blog.csdn.net/WhiffeYF/article/details/142132328 https://arxiv.org/pdf/2312.15746 速覽 破解大語言模型在推薦系統中的不穩定性 該論文聚焦于大語言模型&#xff08;LLMs&#xff09;在推薦系統中的應用問題&#xff0c;指出…

Linux的使用——FinalShell下載使用及連接云服務器的教程

一、注冊免費阿里云服務器 1. 進入阿里云服務器官網 阿里云-計算&#xff0c;為了無法計算的價值https://www.aliyun.com/?spm5176.ecscore_server.console-base_top-nav.dlogo.39144df5uvPLOm 2. 點擊免費試用 這里我已經試用過了&#xff0c;大家選擇合適的云服務器點擊立…

如何清理 Docker 占用的巨大磁盤空間

我相信很多人在使用 Docker 一段時間后&#xff0c;都會遇到一個常見問題&#xff1a;磁盤空間被迅速吃光&#xff0c;尤其是在進行頻繁的鏡像構建、測試和運行容器時。以我自己為例&#xff0c;在 Ubuntu 24.04設備上&#xff0c;docker system df -v 一看&#xff0c;Docker …

【CMake】緩存變量

目錄 一. 緩存變量 二.創建緩存變量 2.1.使用set()來創建緩存變量 2.2.使用FORCE參數來覆蓋緩存變量 2.2.1.示例1——不帶force的set是不能覆蓋已經存在的緩存變量的 2.2.2.示例2——帶force的set才能覆蓋已經存在的緩存變量 2.2.3.對比示例 2.3.命令行 -D 創建/覆蓋緩…

vue2使用若依框架動態新增tab頁并存儲之前的tab頁的操作

1. 應用場景&#xff1a;點擊歷史記錄&#xff0c;要比較兩個tab頁的內容時&#xff0c;需要做到切換tab頁來回看左右對數據對比。2.開發難點若依項目正常是把路由配置到菜單管理里&#xff0c;都是設定好的。不過它也給我們寫好了動態新增tab頁的方&#xff0c;需要我們自己來…

論文閱讀-SelectiveStereo

文章目錄1 概述2 模塊2.1 SelectiveIGEV和IGEV的差異2.2 上下文空間注意力2.2.1 通道注意力2.2.2 空間注意力2.3 SRU3 效果參考資料1 概述 本文主要結合代碼對Selective的創新點進行針對性講解&#xff0c;相關的背景知識可以參考我寫的另兩篇文章論文閱讀-RaftStereo和論文閱…

深入分析神馬 M56S+ 202T 礦機參數與性能特點

引言在比特幣&#xff08;BTC&#xff09;和比特幣現金&#xff08;BCH&#xff09;等主流加密貨幣的挖掘過程中&#xff0c;礦機的選擇直接關系到挖礦的效率與收益。神馬 M56S 202T礦機是SHA-256算法的礦機&#xff0c;憑借其強大的算力和高效的能效比&#xff0c;成為了礦工們…