數據結構 學習 隊列 2025年6月14日 11點22分

循環隊列

循環隊列是一種線性數據結構,它遵循FIFO(先進先出)原則,但與普通隊列不同的是,循環隊列的最后一個元素連接回第一個元素,形成一個環形結構。這種設計有效解決了普通隊列的"假溢出"問題,可以更高效地利用存儲空間。

基本概念

1. 循環隊列特點

  • 環形結構:隊尾連接隊首,形成循環

  • 高效空間利用:重用出隊元素釋放的空間

  • 兩個指針:front(隊首)和rear(隊尾)

  • 判空判滿:需要特殊處理區分隊列空和滿的狀態

2. 基本操作

  • Enqueue:向隊尾添加元素

  • Dequeue:從隊首移除元素

  • Front:獲取隊首元素

  • Rear:獲取隊尾元素

  • isEmpty:判斷隊列是否為空

  • isFull:判斷隊列是否已滿

實際應用
  1. CPU任務調度:循環分配CPU時間片

  2. 內存管理:循環緩沖區處理數據流

  3. 網絡數據包處理:按順序處理到達的數據包

  4. 打印機隊列:管理多個打印任務

  5. 音樂播放列表:循環播放歌曲

//數組實現(固定大小)
class CircularQueue {
private:vector<int> data;int front;int rear;int size;public:CircularQueue(int k) {data.resize(k);front = -1;rear = -1;size = k;}bool enQueue(int value) {if (isFull()) return false;if (isEmpty()) front = 0;rear = (rear + 1) % size;data[rear] = value;return true;}bool deQueue() {if (isEmpty()) return false;if (front == rear) {front = -1;rear = -1;} else {front = (front + 1) % size;}return true;}int Front() {if (isEmpty()) return -1;return data[front];}int Rear() {if (isEmpty()) return -1;return data[rear];}bool isEmpty() {return front == -1;}bool isFull() {return (rear + 1) % size == front;}
};
//鏈表實現
class Node {
public:int val;Node* next;Node(int value) : val(value), next(nullptr) {}
};class LinkedCircularQueue {
private:Node *front, *rear;public:LinkedCircularQueue() : front(nullptr), rear(nullptr) {}bool enQueue(int value) {Node* newNode = new Node(value);if (rear == nullptr) {front = rear = newNode;} else {rear->next = newNode;rear = newNode;}rear->next = front; // 形成循環return true;}bool deQueue() {if (isEmpty()) return false;int value = front->val;Node* temp = front;if (front == rear) {front = rear = nullptr;} else {front = front->next;rear->next = front; // 保持循環}delete temp;return true;}int Front() {if (isEmpty()) return -1;return front->val;}int Rear() {if (isEmpty()) return -1;return rear->val;}bool isEmpty() {return front == nullptr;}// 鏈表實現通常不考慮滿的情況(除非內存耗盡)bool isFull() {return false; }
};
示例
#include <iostream>
#include <vector>using namespace std;class CircularQueue {
private:vector<int> data;  // 使用vector存儲隊列元素int front;         // 隊首指針int rear;          // 隊尾指針int size;          // 隊列容量public:// 構造函數,初始化隊列容量CircularQueue(int k) {data.resize(k); // 分配存儲空間front = -1;     // 初始時隊首指針為-1表示空隊列rear = -1;      // 初始時隊尾指針為-1表示空隊列size = k;       // 設置隊列容量}// 入隊操作bool enQueue(int value) {if (isFull()) {  // 檢查隊列是否已滿cout << "隊列已滿,無法插入 " << value << endl;return false;}if (isEmpty()) { // 如果是第一個元素front = 0;   // 初始化隊首指針}rear = (rear + 1) % size; // 循環移動隊尾指針data[rear] = value;       // 存儲元素cout << "插入 " << value << " 成功" << endl;return true;}// 出隊操作bool deQueue() {if (isEmpty()) {  // 檢查隊列是否為空cout << "隊列為空,無法刪除" << endl;return false;}int value = data[front]; // 獲取隊首元素if (front == rear) {     // 如果隊列中只有一個元素front = -1;          // 重置隊首指針rear = -1;           // 重置隊尾指針} else {front = (front + 1) % size; // 循環移動隊首指針}cout << "刪除 " << value << " 成功" << endl;return true;}// 獲取隊首元素int Front() {if (isEmpty()) return -1; // 隊列為空返回-1return data[front];       // 返回隊首元素}// 獲取隊尾元素int Rear() {if (isEmpty()) return -1; // 隊列為空返回-1return data[rear];        // 返回隊尾元素}// 判斷隊列是否為空bool isEmpty() {return front == -1; // 隊首指針為-1表示空隊列}// 判斷隊列是否已滿bool isFull() {return (rear + 1) % size == front; // 隊尾下一個位置是隊首表示隊列已滿}// 顯示隊列內容void display() {if (isEmpty()) {  // 檢查隊列是否為空cout << "隊列為空" << endl;return;}cout << "隊列元素: ";if (rear >= front) {  // 隊列元素沒有跨越數組邊界for (int i = front; i <= rear; i++)cout << data[i] << " ";} else {  // 隊列元素跨越數組邊界(循環情況)for (int i = front; i < size; i++)  // 打印隊首到數組末尾的元素cout << data[i] << " ";for (int i = 0; i <= rear; i++)    // 打印數組開頭到隊尾的元素cout << data[i] << " ";}cout << endl;}
};int main() {// 創建容量為5的循環隊列CircularQueue q(5);// 入隊操作測試q.enQueue(1);q.enQueue(2);q.enQueue(3);q.enQueue(4);q.enQueue(5);q.enQueue(6); // 隊列已滿,無法插入// 顯示隊列內容q.display();// 出隊操作測試q.deQueue();q.deQueue();// 顯示隊列內容q.display();// 繼續入隊測試循環特性q.enQueue(6);q.enQueue(7);// 顯示隊列內容q.display();// 獲取隊首和隊尾元素cout << "隊首元素: " << q.Front() << endl;cout << "隊尾元素: " << q.Rear() << endl;return 0;
}

雙向隊列

雙向隊列是一種非常實用的數據結構,它提供了比普通隊列和棧更靈活的操作方式,在算法設計和系統開發中都有廣泛應用。

一種允許在兩端進行插入和刪除操作的線性數據結構。它結合了棧和隊列的特性,提供了更靈活的數據操作方式。

基本概念
1. 雙向隊列特點
  • 雙端操作:可以在隊首和隊尾進行插入和刪除

  • 靈活性強:既可以作為隊列使用(FIFO),也可以作為棧使用(LIFO)

  • 多種實現方式:可以使用數組或鏈表實現

2. 基本操作
  • push_front:在隊首插入元素

  • push_back:在隊尾插入元素

  • pop_front:刪除隊首元素

  • pop_back:刪除隊尾元素

  • front:獲取隊首元素

  • back:獲取隊尾元素

  • size:獲取元素數量

  • empty:判斷是否為空

//基與雙鏈表實現#include <iostream>
using namespace std;// 雙向鏈表節點
struct Node {int data;Node* prev;Node* next;Node(int val) : data(val), prev(nullptr), next(nullptr) {}
};class Deque {
private:Node* front;Node* rear;int count;public:Deque() : front(nullptr), rear(nullptr), count(0) {}~Deque() {while (!empty()) {pop_front();}}// 在隊首插入void push_front(int val) {Node* newNode = new Node(val);if (empty()) {front = rear = newNode;} else {newNode->next = front;front->prev = newNode;front = newNode;}count++;}// 在隊尾插入void push_back(int val) {Node* newNode = new Node(val);if (empty()) {front = rear = newNode;} else {newNode->prev = rear;rear->next = newNode;rear = newNode;}count++;}// 刪除隊首元素void pop_front() {if (empty()) {cout << "Deque is empty!" << endl;return;}Node* temp = front;front = front->next;if (front == nullptr) {rear = nullptr;} else {front->prev = nullptr;}delete temp;count--;}// 刪除隊尾元素void pop_back() {if (empty()) {cout << "Deque is empty!" << endl;return;}Node* temp = rear;rear = rear->prev;if (rear == nullptr) {front = nullptr;} else {rear->next = nullptr;}delete temp;count--;}// 獲取隊首元素int get_front() {if (empty()) {cout << "Deque is empty!" << endl;return -1;}return front->data;}// 獲取隊尾元素int get_back() {if (empty()) {cout << "Deque is empty!" << endl;return -1;}return rear->data;}// 獲取元素數量int size() {return count;}// 判斷是否為空bool empty() {return count == 0;}// 打印隊列內容void display() {Node* current = front;cout << "Deque: [";while (current != nullptr) {cout << current->data;if (current->next != nullptr) {cout << ", ";}current = current->next;}cout << "]" << endl;}
};
//基于循環數組的實現
#include <iostream>
#include <vector>
using namespace std;class ArrayDeque {
private:vector<int> data;int front;int rear;int capacity;int count;public:ArrayDeque(int k) : capacity(k), front(0), rear(0), count(0) {data.resize(k);}// 在隊首插入bool push_front(int val) {if (isFull()) {cout << "Deque is full!" << endl;return false;}front = (front - 1 + capacity) % capacity;data[front] = val;count++;return true;}// 在隊尾插入bool push_back(int val) {if (isFull()) {cout << "Deque is full!" << endl;return false;}data[rear] = val;rear = (rear + 1) % capacity;count++;return true;}// 刪除隊首元素bool pop_front() {if (isEmpty()) {cout << "Deque is empty!" << endl;return false;}front = (front + 1) % capacity;count--;return true;}// 刪除隊尾元素bool pop_back() {if (isEmpty()) {cout << "Deque is empty!" << endl;return false;}rear = (rear - 1 + capacity) % capacity;count--;return true;}// 獲取隊首元素int get_front() {if (isEmpty()) {cout << "Deque is empty!" << endl;return -1;}return data[front];}// 獲取隊尾元素int get_back() {if (isEmpty()) {cout << "Deque is empty!" << endl;return -1;}return data[(rear - 1 + capacity) % capacity];}// 判斷是否為空bool isEmpty() {return count == 0;}// 判斷是否已滿bool isFull() {return count == capacity;}// 獲取元素數量int size() {return count;}// 打印隊列內容void display() {cout << "Deque: [";for (int i = 0; i < count; i++) {cout << data[(front + i) % capacity];if (i < count - 1) {cout << ", ";}}cout << "]" << endl;}
};

實際應用
  1. 撤銷操作:許多編輯器使用雙向隊列實現撤銷功能

  2. 滑動窗口:解決滑動窗口最大值等問題

  3. 任務調度:操作系統中的任務調度算法

  4. 瀏覽器歷史記錄:前進和后退功能

  5. 回文檢查:可以從兩端同時檢查字符

?示例代碼
int main() {// 測試鏈表實現的Dequecout << "Linked List Deque:" << endl;Deque dq;dq.push_back(10);dq.push_back(20);dq.push_front(5);dq.display(); // [5, 10, 20]cout << "Front: " << dq.get_front() << endl; // 5cout << "Back: " << dq.get_back() << endl;   // 20dq.pop_front();dq.display(); // [10, 20]dq.pop_back();dq.display(); // [10]// 測試數組實現的Dequecout << "\nArray Deque:" << endl;ArrayDeque adq(5);adq.push_back(100);adq.push_front(50);adq.push_back(200);adq.display(); // [50, 100, 200]cout << "Front: " << adq.get_front() << endl; // 50cout << "Back: " << adq.get_back() << endl;   // 200adq.pop_front();adq.display(); // [100, 200]adq.pop_back();adq.display(); // [100]return 0;
}

單調隊列

單調隊列是一種特殊的隊列數據結構,它保持隊列中元素的單調性(單調遞增或單調遞減)。這種數據結構常用于解決滑動窗口相關問題,能夠高效地獲取窗口中的最大值或最小值。

單調隊列通過維護數據的單調性,將原本O(nk)的滑動窗口問題優化到O(n),是解決一類極值問題的有效工具。掌握其核心思想和實現技巧對算法能力提升有很大幫助

基本概念
1. 單調隊列特性
  • 單調性:隊列中元素保持單調遞增或單調遞減

  • 雙端操作:可以從隊首和隊尾進行插入和刪除

  • 高效性:能在O(1)時間內獲取當前窗口的最大值/最小值

2. 常見應用場景
  • 滑動窗口最大值/最小值

  • 股票價格分析

  • 數據流中的極值問題

  • 動態規劃優化

//單調遞減隊列 用于求滑動窗口最大值)#include <deque>
#include <vector>using namespace std;class MonotonicQueue {
private:deque<int> data; // 存儲元素的下標public:// 在隊尾添加元素,維護單調遞減性void push(int idx, const vector<int>& nums) {while (!data.empty() && nums[data.back()] <= nums[idx]) {data.pop_back(); // 移除比當前元素小的元素}data.push_back(idx);}// 獲取當前隊列最大值(隊首元素)int max() {return data.front();}// 移除超出窗口范圍的元素void pop(int idx) {while (!data.empty() && data.front() <= idx) {data.pop_front();}}// 判斷隊列是否為空bool empty() {return data.empty();}
};vector<int> maxSlidingWindow(vector<int>& nums, int k) {vector<int> result;MonotonicQueue mq;// 初始化第一個窗口for (int i = 0; i < k; ++i) {mq.push(i, nums);}result.push_back(nums[mq.max()]);// 滑動窗口for (int i = k; i < nums.size(); ++i) {mq.pop(i - k); // 移除離開窗口的元素mq.push(i, nums); // 添加新元素result.push_back(nums[mq.max()]);}return result;
}
//單調遞增隊列 用于求滑動窗口最小值)
class MonotonicQueueMin {
private:deque<int> data; // 存儲元素的下標public:void push(int idx, const vector<int>& nums) {while (!data.empty() && nums[data.back()] >= nums[idx]) {data.pop_back(); // 移除比當前元素大的元素}data.push_back(idx);}int min() {return data.front();}void pop(int idx) {while (!data.empty() && data.front() <= idx) {data.pop_front();}}bool empty() {return data.empty();}
};vector<int> minSlidingWindow(vector<int>& nums, int k) {vector<int> result;MonotonicQueueMin mq;for (int i = 0; i < k; ++i) {mq.push(i, nums);}result.push_back(nums[mq.min()]);for (int i = k; i < nums.size(); ++i) {mq.pop(i - k);mq.push(i, nums);result.push_back(nums[mq.min()]);}return result;
}
經典應用
//滑動窗口最大值
vector<int> maxSlidingWindow(vector<int>& nums, int k) {vector<int> res;deque<int> dq; // 存儲下標for (int i = 0; i < nums.size(); ++i) {// 移除超出窗口范圍的元素while (!dq.empty() && dq.front() <= i - k) {dq.pop_front();}// 維護單調遞減性while (!dq.empty() && nums[dq.back()] <= nums[i]) {dq.pop_back();}dq.push_back(i);// 窗口形成后開始記錄結果if (i >= k - 1) {res.push_back(nums[dq.front()]);}}return res;
}
//隊列的最大值class MaxQueue {
private:queue<int> data;deque<int> max_q;public:MaxQueue() {}int max_value() {if (max_q.empty()) return -1;return max_q.front();}void push_back(int value) {data.push(value);while (!max_q.empty() && max_q.back() < value) {max_q.pop_back();}max_q.push_back(value);}int pop_front() {if (data.empty()) return -1;int val = data.front();data.pop();if (val == max_q.front()) {max_q.pop_front();}return val;}
};
//股票的價格跨度
class StockSpanner {
private:stack<pair<int, int>> st; // {price, span}public:StockSpanner() {}int next(int price) {int span = 1;while (!st.empty() && st.top().first <= price) {span += st.top().second;st.pop();}st.push({price, span});return span;}
};

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

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

相關文章

打造絲滑滾動體驗:Scroll-driven Animations 正式上線!

&#x1f300; 打造絲滑滾動體驗&#xff1a;Scroll-driven Animations 正式上線&#xff01; &#x1f6a8; 告別 JS 手動監聽滾動條&#xff0c;CSS 新能力讓你用兩行代碼實現高級滾動動效。 &#x1f50d; 什么是 Scroll-driven Animations&#xff1f; Scroll-driven anim…

知識體系_研究模型_價格敏感度測試模型(PSM)

1 概述 價格敏感度測試模型(Price Sensitivity Measurement,PSM) ,通過調研潛在用戶對于不同價格的滿意或接受程度,從而制定出合適的產品價格。 價格敏感度PSM模型的分析一般分為以下幾個步驟: (1)確定多個價格 (2)通過一定的方式(通常是問卷)收集目標客戶對不同價…

C++11函數封裝器 std::function

? 1. 什么是 std::function std::function 是 C11 引入的標準庫工具&#xff0c;是一個通用的函數封裝器&#xff0c;可以包裝以下任意可調用對象&#xff1a; 普通函數Lambda 表達式函數指針成員函數指針函數對象&#xff08;也叫仿函數&#xff0c;定義了 operator() 的類…

centos系統docker配置`milvus-standalone`教程

本人使用的是京東云服務器docker配置milvus 參考教程&#xff1a;https://blog.csdn.net/withme977/article/details/137270087 需要注意&#xff1a;虛擬機安裝pymilvus和docker安裝milvus版本需要對應&#xff0c;否則會出現connection失敗問題 查看虛擬機pymilvus版本&…

AI for 數據分析:技術演進與應用實踐

一、AI 數據分析的核心定義與技術演進 概念延伸&#xff1a;從傳統分析到智能分析 傳統數據分析工作&#xff0c;主要依賴人工使用 Excel、SPSS 等統計工具進行建模與分析。這種方式不僅效率較低&#xff0c;而且對專業人員的依賴度極高。而 AI 驅動的數據分析則借助機器學習…

stm32 f103c8t6仿真 串口收發測試

C8T6串口概述 STM32F103C8T6微控制器包含3個串口模塊&#xff1a; USART1 (高級串口) USART2 USART3 (部分型號可能標記為UART3) 引腳分布圖 USART1 (串口1) 基本特性 類型&#xff1a;全功能USART(通用同步異步收發器) 通信模式&#xff1a; 全雙工異步通信 單線半…

語言特性適用的場景:衛星、火箭控制系統用什么開發語言?

核心飛行控制系統開發語言 衛星、火箭及相關航天系統的軟件開發對可靠性、實時性、安全性有極高要求&#xff0c;因此語言選擇需嚴格匹配這些需求。以下是航天領域常用的編程語言及其應用場景分析&#xff1a; 一、核心飛行控制與嵌入式系統&#xff1a;C、C、Ada 航天器的核…

AI for Science:智能科技如何重塑科學研究

AI與科學研究的邂逅 人工智能&#xff08;Artificial Intelligence&#xff0c;簡稱AI&#xff09;作為一門致力于模擬人類智能的交叉學科&#xff0c;近年來已經從實驗室走向現實世界的各個角落&#xff0c;而科學研究領域正是其最具變革潛力的舞臺之一。AI的核心在于通過算法…

項目三 - 任務7:開發名片管理系統

在本次項目三的任務7中&#xff0c;我們成功開發了一個功能全面的名片管理系統。該系統采用Java語言&#xff0c;基于MVC&#xff08;模型-視圖-控制器&#xff09;架構模式&#xff0c;實現了用戶登錄、名片的增刪改查等核心功能。通過設計Card類來封裝名片信息&#xff0c;Ca…

MySQL 8.0 OCP 英文題庫解析(十八)

Oracle 為慶祝 MySQL 30 周年&#xff0c;截止到 2025.07.31 之前。所有人均可以免費考取原價245美元的MySQL OCP 認證。 從今天開始&#xff0c;將英文題庫免費公布出來&#xff0c;并進行解析&#xff0c;幫助大家在一個月之內輕松通過OCP認證。 本期公布試題161~170 試題1…

leetcode_503 下一個更大元素

1. 題意 在一個循環數組中&#xff0c;找到下一個比它大的數。 2. 題解 也不知道怎么就單調棧了&#xff0c;可能是刷出來的吧。。。 還是來解釋一下吧&#xff01;&#xff01;&#xff01; 如果有新元素入棧 c c c&#xff0c; 那么在棧內的元素只要小于新元素的 s s s…

在postgresql中,group by時取第一個值

在postgresql中,group by時,uuid類型的字段可以用哪個聚集函數: SELECT create_user , (array_agg(myid))[1] AS first_uuid FROM "t_resource_data" GROUP BY create_user 人大金倉、PostgreSQL使用GROUP BY聚合后&#xff0c;取第一個值或最后一個值的辦_pgsql gro…

【FineDance】ModuleNotFoundError: No module named ‘pytorch3d‘

pytorch3d Traceback (most recent call last): File “/home/zhangbin/perfwork/01_ai/13_FineDance/data/code/pre_motion.py”, line 12, in from dataset.quaternion import ax_to_6v, ax_from_6v File “/home/zhangbin/perfwork/01_ai/13_FineDance/dataset/quaternion.…

MySQL 調優筆記

1.如何定位慢查詢? 定位慢查詢主要依靠 MySQL 的慢查詢日志配合工具如 pt-query-digest &#xff0c;mysqldumpslow 進行分析&#xff0c;或者通過 performance_schema 進行實時監控&#xff0c;進一步可以使用 EXPLAIN 分析執行計劃。 -> 開啟慢查詢日志 -- 查看慢查詢…

嵌入式 STM32 開發問題:燒錄 STM32CubeMX 創建的 Keil 程序沒有反應

燒錄 STM32CubeMX 創建的 Keil 程序沒有反應問題原因 大概率是因為沒有勾選 Reset and Run&#xff0c;程序成功燒錄到&#xff0c;但芯片不會自動復位并執行&#xff0c;而是保持停止狀態 處理策略 在 Keil 中勾選 Reset and Run 點擊 【Options for Target】 點擊 【Debu…

Flower框架中noise_multiplier與clipped_count_stddev的關系

noise_multiplier 與 clipped_count_stddev 的數學關系 在差分隱私聯邦學習中&#xff0c;noise_multiplier 和 clipped_count_stddev 是兩個核心參數&#xff0c;它們共同決定了隱私保護強度和模型精度的權衡。理解它們的關系需要從差分隱私的數學原理入手&#xff1a; 1. 高…

Laravel 從版本 5 到 12 每個版本都引入了一些新的特性、改進和棄用的功能

Laravel 從版本 5 到 12 經歷了多次更新,每個版本都引入了一些新的特性、改進和棄用的功能。下面是這些主要版本之間的關鍵區別: Laravel 5 Lumen: 引入了微框架 Lumen。Elixir: Elixir 是一個用于編譯和合并前端資源的工具,后來被 Laravel Mix 取代。Middleware Groups: 引…

Lambda 表達式的語法與使用:更簡潔、更靈活的函數式編程!

全文目錄&#xff1a; 開篇語Lambda 表達式的語法與使用&#xff1a;更簡潔、更靈活的函數式編程一、Lambda 表達式的語法1.1 Lambda 表達式的基本語法形式 二、Lambda 表達式的使用2.1 Lambda 表達式與匿名內部類的對比代碼示例&#xff1a;使用匿名內部類和 Lambda 表達式實現…

從0到1開發一個自己的工具 MCP 并發布到 test PyPi(Python個人版)

目錄 1. 我理解的 MCP2. 寫一個自己的MCP然后發布到 PyPi 上&#xff0c;包括加法工具和獲取當前 ip 工具2.1 先碎碎念一下 uv2.2 初始化項目&#xff08;全程在 cmd 下運行命令&#xff09;2.3 添加 mcp 依賴2.4 添加 server.py&#xff0c;先把加法功能添加上2.5 運行并測試加…