數據結構*隊列

隊列

什么是隊列

是一種線性的數據結構,和棧不同,隊列遵循“先進先出”的原則。如下圖所示:
在這里插入圖片描述

在這里插入圖片描述
在集合框架中我們可以看到LinkedList類繼承了Queue類(隊列)。

普通隊列(Queue)

Queue中的方法

方法功能
add()入隊列
offer()入隊列
remove()出隊列
poll()出隊列
element()獲取隊頭元素
peek()獲取隊頭元素

add()和offer()都是添加數據、remove()和poll()都是刪除數據、element()和peek()都是獲取隊列頭部元素信息這些方法有什么區別呢?(下面都是豆包總結的,可以參考一下)
在這里插入圖片描述
在這里插入圖片描述
總結:
add()、remove()、element()方法對于滿和空隊列的時候會拋出異常。而offer()、poll()、peek()方法不會,它們更具有靈活性。我們則常用offer()、poll()、peek()方法來對隊列進行操作。

其他方法

在Collection接口中還有size()、isEmpty()等其他方法我們可以使用。

模擬實現隊列

用鏈表實現

在這里插入圖片描述

public class MyQueue {static class ListNode{private final int val;private ListNode next;private ListNode prev;private ListNode(int val) {this.val = val;}}public ListNode first;public ListNode last;/*** 入隊操作:尾插法* @param val*/public void offer(int val) {ListNode node = new ListNode(val);if(empty()) {first = last = node;}last.next = node;node.prev = last;last = last.next;}/*** 出隊操作:刪除頭節點* @return*/public int poll() {if(empty()) {return -1;}int value = first.val;if(first == last) {first = last = null;return value;}else {first = first.next;first.prev = null;return first.val;}}/*** 獲得頭節點不刪除* @return*/public int peek() {if(empty()) {return -1;}return first.val;}/*** 獲得有效數據* @return*/public int size() {ListNode cur = first;int usedSize = 0;while (cur != null) {usedSize++;cur = cur.next;}return usedSize;}/*** 判斷是否為空* @return*/public boolean empty() {return first == null;}
}

循環隊列

對于普通的數組來說,再用隊列的思想時,很容易造成數組下標越界等問題。這時候我們可以將數組循環起來。如下圖所示:
在這里插入圖片描述
這時候就產生問題了。

1、rear 和 front 如何訪問從最后一個下標訪問到0下標?

由于循環,可以將(下標+偏移量)/ length。這里的偏移量為1(每次只走一格)。也就是對于有關下標的需要用(rear+1) / len(front+1) / len

2、如何判斷數組是否滿了。

解決的方法有:
1、使用size個數,當等于數組長度,則說明滿了;
2、用一個boolean值來標記是否滿了。初始時,front == rearisFull == false。當每次添加數據時判斷 front == rear,當相等時isFull == true,說明滿了。在刪除數據時,不可能滿了,將isFull == false
3、留出一個空間來判斷是否滿了。當rear的下一個是front的時候,就說明是滿的。
在這里插入圖片描述
在入隊時,放一個元素,rear往后走,一開始 rear == front。當rear的下一個是front的時候,也就只存放了 len - 1個數據。

代碼展示:

采用預留空間的方法

class MyCircularQueue {public int[] elem;int rear = 0;int front = 0;public MyCircularQueue(int k) {elem = new int[k];//由于采用預留空間的方法,使得實際數據只有k - 1個}/*** 向循環列隊中插入一個元素* @param value* @return*/public boolean enQueue(int value) {if(isFull()) {return false;}elem[rear] = value;//rear指向預留的空間rear = (rear + 1) % elem.length;//這樣rear下標始終控制在合理范圍return true;}/*** 刪除循環列隊中的一個元素* 由于隊列是先進先出的,所以刪除的是front下標的元素* @return*/public boolean deQueue() {if(isEmpty()) {return false;}front = (front + 1) % elem.length;//這樣front下標始終控制在合理范圍return true;}/*** 從隊首獲取元素* @return*/public int Front() {if(isEmpty()) {return -1;}return elem[front];}/*** 獲取隊尾元素* @return*/public int Rear() {if(isEmpty()) {return -1;}//rear并不是隊尾元素,rear的上一個才是。//rear - 1就得到了,但當rear為0時,rear - 1 就會越界,這時候就要if判斷了if(rear == 0) {return elem[elem.length - 1];}return elem[rear - 1];}/*** 判斷循環隊列是否為空* @return*/public boolean isEmpty() {return rear == front;}/*** 判斷循環隊列是否滿了* @return*/public boolean isFull() {return (rear + 1) % elem.length == front;//rear為預留空間,下一個指向front}
}

雙端隊列(Deque)

它是一種特殊的隊列,允許在隊列的兩端進行元素的插入與刪除操作。這意味著既能在隊列頭部添加或移除元素,也能在隊列尾部添加或移除元素。一般創建ArrayDequeLinkedList這兩個類的對象。
ArrayDeque是用數組實現的雙端隊列,LinkedList是用雙向鏈表實現的雙端隊列。其中的優缺點和順序表與鏈表的優缺點類似。
對于雙端隊列的方法是在Queue方法名中后面加上Last、First(例如:offerFirst()、pollFirst()、peekLast()等,但要注意的是:對于拋異常的獲取元素并不是用的element()而是getFirst()和getLast() )。

代碼展示:

public static void test1() {Deque<Integer> deque = new ArrayDeque<>();deque.offerFirst(1);deque.offerFirst(10);deque.offerFirst(100);deque.offerFirst(1000);deque.offerLast(2);deque.offerLast(20);System.out.println(deque);deque.pollFirst();//出隊列的頭元素:1000System.out.println(deque);deque.pollLast();//出隊列的尾元素:20System.out.println(deque);System.out.println(deque.peekFirst());System.out.println(deque.peekLast());System.out.println(deque);
}
public static void test2() {Deque<Integer> deque = new LinkedList<>();deque.offerFirst(1);deque.offerFirst(10);deque.offerFirst(100);deque.offerFirst(1000);deque.offerLast(2);deque.offerLast(20);System.out.println(deque);deque.pollFirst();//出隊列的頭元素:1000System.out.println(deque);deque.pollLast();//出隊列的尾元素:20System.out.println(deque);System.out.println(deque.peekFirst());System.out.println(deque.peekLast());System.out.println(deque);
}

ArrayDequeLinkedList兩個實現的效果是一樣的。

用隊列實現棧

首先一個隊列肯定是實現不了棧的,兩個運行邏輯都不一樣,一個先進先出,一個先進后出。此時需要兩個隊列來實現棧。
在這里插入圖片描述
對于出"棧"方法:將其余數據依次放入空隊列中(對非空隊列進行出"棧"操作)。
在這里插入圖片描述
對于入"棧",只需要將元素放入非空的隊列中即可。
在這里插入圖片描述
對于拿到"棧"頂的元素,前面和出"棧"一樣:將其余數據依次放入空隊列中,直接輸出剩下的元素,在將剩下的元素放到另一個隊列中。
在這里插入圖片描述

代碼展示:

import java.util.LinkedList;
import java.util.Queue;class MyStack {public Queue<Integer> queue1;public Queue<Integer> queue2;public MyStack() {queue1 = new LinkedList<>();queue2 = new LinkedList<>();}/*** 入棧* @param x*/public void push(int x) {if(!queue1.isEmpty()) {queue1.offer(x);}else if(!queue2.isEmpty()) {queue2.offer(x);}else {queue1.offer(x);}}/*** 出棧* @return*/public int pop() {//當都為空時,說明"棧"中沒有元素if(empty()) {return -1;}//對于非空隊列進行操作if(!queue1.isEmpty()) {int size = queue1.size();//將其余元素移到空隊列while (size != 1) {queue2.offer(queue1.poll());size--;}//返回隊列中僅有的元素,并刪除return queue1.poll();}else {//下面是!queue2.isEmpty()的情況int size = queue2.size();while (size != 1) {queue1.offer(queue2.poll());size--;}return queue2.poll();}}/*** 獲取"棧"頂元素* @return*/public int top() {//判斷棧是否為空if(empty()) {return -1;}if(!queue1.isEmpty()) {int size = queue1.size();while (size != 1) {queue2.offer(queue1.poll());size--;}//上述操作和出棧一樣,下面只需輸出元素,并不刪除數據int value = queue1.poll();queue2.offer(value);//將元素入隊,避免丟失return value;}else {int size = queue2.size();while (size != 1) {queue1.offer(queue2.poll());size--;}int value = queue2.poll();queue1.offer(value);return value;}}public boolean empty() {return queue1.isEmpty() && queue2.isEmpty();//當隊列都為空時,說明"棧"為空}
}

用棧實現隊列

同樣的,也是需要兩個棧的。
在這里插入圖片描述
對于出"隊列",只需要將非空棧(stack1)中的元素全部放到另一個棧中(stack2),再從stack2中出元素。
在這里插入圖片描述
當stack2為空,則將stack1全部放入stack2中。
在這里插入圖片描述
對于入"隊列"來說,只需要將元素放到stack1中。
在這里插入圖片描述

代碼展示:

import java.util.Stack;class MyQueue {public Stack<Integer> stack1;public Stack<Integer> stack2;public MyQueue() {stack1 = new Stack<>();stack2 = new Stack<>();}public void push(int x) {stack1.push(x);}public int pop() {if(empty()) {return -1;}if (stack2.empty()) {while (!stack1.empty()) {//需要將stack1中的元素 全部 放到stack2中(用while循環)stack2.push(stack1.pop());}}return stack2.pop();//stack2棧中有元素,直接調用方法}public int peek() {if(empty()) {return -1;}if (stack2.empty()) {while (!stack1.empty()) {stack2.push(stack1.pop());}}return stack2.peek();}public boolean empty() {return stack1.empty() && stack2.empty();}
}

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

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

相關文章

Nginx — 防盜鏈配置

防盜鏈簡述 防盜鏈是一種保護網絡資源所有者權益的技術手段&#xff0c;旨在防止未經授權的用戶或網站通過直接鏈接的方式盜用資源&#xff0c;以下是關于防盜鏈的簡述&#xff1a; 原理 基于請求頭驗證&#xff1a;服務器通過檢查請求頭中的特定字段&#xff0c;如Referer字…

【淺學】Windows下ffmpeg+nginx+flv將本地視頻推流在本地搭建的Web前端頁面中播放,超詳細步驟

Nginx安裝和配置 下載nginx-1.19.3-http-flv 模塊預編譯包并解壓放在d盤&#xff0c;路徑就跟安裝步驟里說的一樣(如下圖)&#xff0c;不然會有其他問題出現。 打開conf/nginx.conf&#xff0c;查看RTMP和http相關的配置&#xff0c;確認端口號和路由名稱 ffpemg推流視頻…

Ubuntu-tomcat安裝部署

https://blog.csdn.net/weixin_43877427/article/details/144697087 Linux下Tomcat安裝與配置_tomcat linux安裝及配置教程-CSDN博客 一、下載Tomcat 1、官網下載 進入后根據自己需要選擇不同的版本&#xff0c;點擊download 進入后&#xff0c;在下圖標注的里邊選擇要下載…

希洛激活器策略思路

在復雜多變的外匯市場中&#xff0c;交易者常常尋求有效的工具來輔助決策。 希洛激活器作為一種綜合性的技術指標&#xff0c;結合了江恩理論、CCI&#xff08;商品通道指數&#xff09;和MACD&#xff08;移動平均收斂發散指標&#xff09;&#xff0c;旨在為交易者提供更為全…

n8n工作流自動化平臺的實操:本地化高級部署

一、本地高級部署 1.下載 docker pull docker.n8n.io/n8nio/n8n 2.運行 docker volume create n8n_data docker run -dit --name n8n -p 5678:5678 -v n8n_data:/home/node/.n8n -e N8N_SECURE_COOKIEfalse -e N8N_RUNNERS_ENABLEDtrue -e N8N_ENFORCE_SETTINGS_FIL…

vector和string的迭代器

1. 迭代器的本質 (1) 標準要求 C 標準要求 std::string 和 std::vector 的迭代器必須是 隨機訪問迭代器&#xff08;Random Access Iterator&#xff09;。 指針天然滿足隨機訪問迭代器的所有操作&#xff08;如 、--、n、* 等&#xff09;&#xff0c;因此可以直接用指針實現…

PyCharm代理配置全攻略:系統設置+Python運行環境一鍵搞定

文章目錄 1. 設置系統代理1.1 作用范圍1.2 使用場景1.3 設置步驟 2. 設置 python 運行/調試代理2.1 作用范圍2.2 使用場景2.3 設置步驟 Pycharm 工具作為一款強大的 IDE&#xff0c;其代理配置在實際開發中也是必不可少的&#xff0c;下面介紹下如何配置 Pycharm 的代理。 1. …

stm32 g031g8 flash擦除函數被坑

先記錄一下在擦除的時候由于調用了這個FLASH_PageErase(FLASH_BANK_1, secpos); 導致擦除不成功&#xff0c;寫入失敗。 下面的擦除有問題// 使用 FLASH_PageErase 擦除該頁while ((FLASH->SR & FLASH_SR_BSY1) ! 0); // 等待空閑FLASH_PageErase(FLASH_BANK_1, secpo…

深度學習與 PyTorch 基礎

筆記 1 深度學習簡介 1.1 深度學習概念 深度學習是機器學習的一類算法, 以人工神經網絡為結構, 可以實現自動提取特征 深度學習核心思想是人工神經網絡為結構, 自動提取特征 1.2 深度學習特點 自動提取特征 解釋性差 大量數據和高性能計算能力 非線性轉換(引入非線性因…

【Unity】XLua訪問C#文件

創建NPC.cs&#xff1a; public class NPC { public string name; public int age; public void Say() { Debug.Log("Say:我是未被修改的"); } public static void Say() { Debug.Log("Static Say:我是未被修改的"); } public void Say2(int a) { Debug.Lo…

【第十六屆藍橋杯省賽】比賽心得與經驗分享(PythonA 組)

文章目錄 一、我的成績二、我的備賽經歷三、如何備賽&#xff08;個人觀點&#xff09;1. 基礎語法2. 數據結構3. 算法4. 數學 四、做題技巧與注意事項五、我的題解試題A 偏藍 &#x1f3c6;100%試題B IPV6 &#x1f3c6;0%試題C 2025圖形 &#x1f3c6;100%試題D 最大數字 &am…

基于Springboot+Mysql的校園博客系統(含LW+PPT+源碼+系統演示視頻+安裝說明)

系統功能 管理員功能&#xff1a;首頁、個人中心、博主管理、文章分類管理、文章信息管理、舉報投訴管理、系統管理&#xff1b;博主功能&#xff1a;首頁、個人中心、文章信息管理、舉報投訴管理、我的收藏管理&#xff1b;前臺首頁功能&#xff1a;首頁、文章信息、系統公告…

第三次作業(密碼學)

#include <stdio.h> #include <stdlib.h> // 計算最大公約數 int gcd(int a, int b) { while (b ! 0) { int temp b; b a % b; a temp; } return a; } // 計算模冪運算 int mod_pow(int base, int exponent, int modulus) { …

3.0/Q1,Charls最新文章解讀

文章題目&#xff1a;Association between outdoor artificial light at night and metabolic diseases in middle-aged to older adults-the CHARLS survey DOI&#xff1a;10.3389/fpubh.2025.1515597 中文標題&#xff1a;夜間戶外人工光與中老年人代謝性疾病的關聯-CHARLS調…

MATLAB 中zerophase函數——零相位響應

零相位響應&#xff08;Zero-Phase Response&#xff09;是指濾波器的幅度函數&#xff0c;但相位為零。濾波器的相位響應為零&#xff0c;意味著不同頻率的信號通過濾波器后&#xff0c;其相位不發生任何變化&#xff0c;即信號的波形在時間軸上沒有偏移。 零相位響應指的是當…

馬克思最基本的哲學思想--改造世界以實現人的自由全面發展--deepseek

馬克思的哲學思想可以概括為“改造世界以實現人的自由全面發展”&#xff0c;這句話看似簡單&#xff0c;卻包含了其哲學的核心邏輯。我們可以從三個層面展開分析&#xff1a; 1. “改造世界”——實踐是哲學的終極使命 馬克思在《關于費爾巴哈的提綱》中寫道&#xff1a; “哲…

JAVA學習-練習試用Java實現“一個簡單的文本摘要系統 :基于關鍵詞提取或句子摘要”

問題&#xff1a; java語言編輯&#xff0c;實現一個簡單的文本摘要系統 &#xff1a;基于關鍵詞提取或句子摘要。 解答思路&#xff1a; 實現一個簡單的文本摘要系統&#xff0c;我們可以采用基于關鍵詞提取的方法。以下是一個簡單的Java實現&#xff0c;使用TF-IDF&#xff0…

案例解析:基于量子計算的分子對接-QDOCK(Quantum Docking)

分子對接&#xff08;Moleculardocking&#xff09;在藥物發現中具有重要意義&#xff0c;但對接的計算速度和準確率始終難以平衡&#xff0c;其巨大解搜索空間對傳統計算機來說異常艱巨。 本文通過引入網格點匹配&#xff08;GPM, Grind point matching&#xff09;和特征原子…

【Mytais系列】Datasource模塊:數據源連接

MyBatis 的 DataSource 模塊是框架與數據庫交互的核心基礎設施&#xff0c;負責管理數據庫連接的創建、分配、釋放及池化&#xff0c;直接影響 SQL 執行效率和資源利用率。以下是其核心內容、功能及在 SQL 執行中的作用詳解&#xff1a; 一、DataSource 模塊的核心組件 組件 功…

React 組件prop添加類型

給函數的props做注解 import { useState } from reacttype Props { className:string,title?:string } // 自定義一個Button組件 function Button(props:Props){// 解構出classname\const {className} propsreturn <button className{className}>點擊我</button&g…