序列容器(vector,deque,list)

STL 序列式容器(vectordequelistarrayforward_list)的核心特征是按插入順序存儲元素(元素的邏輯順序與物理存儲順序一致)

?vector

下圖是底層原理 具體點擊鏈接vector介紹

deque(雙端隊列)

在 C++ STL 中,deque(Double-Ended Queue,雙端隊列)是一種支持兩端高效插入 / 刪除的序列式容器,底層通過 “分段動態數組 + 中控數組” 的結構實現,兼顧了隨機訪問能力和雙端操作效率。以下從核心特性、底層原理、常用接口、適用場景等方面全面解析?deque

一、核心特性

  1. 雙端高效操作

    • 頭部(front)和尾部(back)的插入(push_front/push_back)、刪除(pop_front/pop_back)操作均為?O (1) 時間復雜度(無需像?vector?那樣移動大量元素,也無需像?list?那樣分配節點)。
  2. 支持隨機訪問

    • 提供下標運算符([])和?at()?成員函數,可直接訪問指定位置的元素,時間復雜度?O(1)(優于?list?的 O (n),但底層實現比?vector?復雜)。
  3. 動態擴容

    • 容量不足時會自動擴容,但擴容邏輯比?vector?更靈活:vector?擴容需分配新的連續內存并拷貝所有元素(O (n) 開銷),而?deque?只需新增一個 “分段數組” 并更新中控數組(避免大規模拷貝,平均擴容開銷更低)。
  4. 非連續內存存儲

    • 底層并非連續內存(與?vector?不同),而是由多個小型連續內存塊(分段數組)和一個 “中控數組”(存儲各分段數組的地址)組成,通過中控數組實現對分段的管理,對外表現為 “連續的元素序列”。

二、底層原理(為什么能兼顧雙端操作和隨機訪問?)

deque?的底層結構可拆解為兩部分,理解這部分能更清晰其特性來源:

  1. 分段數組(Buffer)

    • 每個分段數組是固定大小的連續內存塊(例如默認 512 字節),用于存儲實際的元素;
    • 分段數組的大小可通過編譯器宏(如?_DEQUE_BUF_SIZE)調整,也可在定義?deque?時通過模板參數指定。
  2. 中控數組(Map)

    • 本質是一個 “指針數組”,每個元素指向一個分段數組;
    • 中控數組會預留一定的空閑位置(頭部和尾部),當頭部需要插入元素且當前首分段已滿時,直接在中控數組頭部新增一個分段指針;尾部同理,避免中控數組頻繁擴容。

訪問元素的邏輯
當通過下標?i?訪問?deque?元素時,底層會先計算?i?所在的 “分段索引”(i / 分段大小)和 “分段內偏移”(i % 分段大小),再通過中控數組找到對應的分段數組,最后通過偏移獲取元素 —— 這一過程是 O (1),因此支持隨機訪問。

三、常用成員函數(核心接口)

deque?的接口與?vector?類似,但新增了雙端操作的接口,以下是高頻使用的成員函數:

類別成員函數功能描述
構造 / 析構deque()默認構造空的?deque
deque(n, val)構造包含?n?個?val?的?deque
deque(beg, end)從迭代器范圍?[beg, end)?構造?deque(如從?vector?或?string?初始化)
雙端操作push_front(val)在頭部插入元素?val(O(1))
push_back(val)在尾部插入元素?val(O(1))
pop_front()刪除頭部元素(O (1),需確保?deque?非空)
pop_back()刪除尾部元素(O (1),需確保?deque?非空)
元素訪問operator[](i)訪問下標?i?處的元素(無越界檢查,越界行為未定義)
at(i)訪問下標?i?處的元素(有越界檢查,越界拋?out_of_range?異常)
front()獲取頭部元素(O (1))
back()獲取尾部元素(O (1))
容量操作size()返回元素個數(O (1))
empty()判斷是否為空(O (1),空返回?true
resize(n, val)調整元素個數為?n:不足補?val,多余刪除
clear()清空所有元素(O (n),元素析構,但中控數組和分段數組可能保留以復用)
迭代器begin()/end()獲取首元素 / 尾后元素的迭代器(支持隨機訪問,可?++/--/+n/-n
rbegin()/rend()獲取反向迭代器(從尾部向頭部遍歷)

四、適用場景(什么時候用?deque?)

deque?的特性決定了它適合 “需要雙端操作 + 隨機訪問” 的場景,典型場景包括:

  1. 實現隊列(Queue)或雙端隊列

    • STL 的?queue?容器適配器默認以?deque?為底層容器(因為?queue?需支持?push_back?和?pop_frontdeque?這兩個操作都是 O (1),優于?vector?的?pop_front(O(n)))。
  2. 頻繁在兩端插入 / 刪除,且需要隨機訪問

    • 例如:滑動窗口算法(需在窗口兩端添加 / 移除元素,同時訪問窗口內任意位置元素)、日志存儲(新日志追加到尾部,舊日志從頭部刪除,偶爾需查詢中間日志)。
  3. 替代?vector?避免大規模擴容開銷

    • 當?vector?存儲大量元素時,擴容會拷貝所有元素,開銷較大;而?deque?擴容只需新增分段,適合元素數量動態增長且規模較大的場景(但隨機訪問效率略低于?vector,需權衡)。

五、與其他容器的對比(vector?vs?list?vs?deque

特性vectorlistdeque
底層結構連續動態數組雙向鏈表分段數組 + 中控數組
隨機訪問([]/at支持(O (1))不支持(O (n))支持(O (1))
頭部插入 / 刪除不支持頭部插入,可以刪除高效(O (1))高效(O (1))
尾部插入 / 刪除高效(O (1),擴容時 O (n))高效(O (1))高效(O (1))
中間插入 / 刪除不高效(O (n))高效(O (1),找位置 O (n))不高效(O (n))
內存利用率高(連續內存,緩存友好)低(節點有指針開銷)中等(分段有少量浪費)
擴容開銷高(拷貝所有元素)低(僅分配新節點)低(新增分段)

六、使用示例(代碼演示)

#include <iostream>
#include <deque>
#include <algorithm>  // 用于 sort 等算法int main() {// 1. 構造 deque 并初始化std::deque<int> dq1;                          // 空 dequestd::deque<int> dq2(5, 10);                   // 5個10:[10,10,10,10,10]std::deque<int> dq3(dq2.begin(), dq2.end());  // 從 dq2 復制:[10,10,10,10,10]// 2. 雙端插入元素dq1.push_back(20);   // 尾部插入:[20]dq1.push_front(10);  // 頭部插入:[10,20]dq1.push_back(30);   // 尾部插入:[10,20,30]// 3. 隨機訪問和遍歷std::cout << "dq1[1] = " << dq1[1] << std::endl;  // 輸出 20(隨機訪問)std::cout << "dq1 遍歷:";for (int i = 0; i < dq1.size(); ++i) {std::cout << dq1[i] << " ";  // 10 20 30}std::cout << std::endl;// 4. 雙端刪除元素dq1.pop_front();  // 刪除頭部:[20,30]dq1.pop_back();   // 刪除尾部:[20]// 5. 排序(支持隨機訪問迭代器,可直接用 sort 算法)std::deque<int> dq4 = {3, 1, 4, 2};std::sort(dq4.begin(), dq4.end());  // 排序后:[1,2,3,4]std::cout << "排序后 dq4:";for (auto val : dq4) {std::cout << val << " ";  // 1 2 3 4}return 0;
}

七、注意事項

  1. 避免中間插入 / 刪除deque?中間插入 / 刪除需要移動該位置兩側的元素(O (n) 時間),效率低,若需頻繁中間操作,優先用?list
  2. 迭代器穩定性deque?的迭代器在擴容時可能失效(中控數組擴容會導致分段指針地址變化),但在兩端插入 / 刪除時,除了首分段和尾分段的迭代器,其他分段的迭代器仍有效(與?vector?所有迭代器失效不同)。
  3. 不適合存儲大對象:每個分段數組存儲元素,若元素體積大,分段數量會減少,但隨機訪問邏輯不變,不過內存碎片可能增加(需結合實際場景權衡)。

總之,deque?是 STL 中 “平衡雙端操作和隨機訪問” 的容器,在需要頻繁操作兩端且需隨機訪問的場景中,是比?vector?和?list?更優的選擇。

list(雙向鏈表)

在 C++ STL 中,std::list?是一種雙向鏈表(雙向非循環鏈表)?容器,其元素通過節點間的指針連接,不要求內存連續。這種結構使其在任意位置的插入和刪除操作上具有獨特優勢,以下從核心特性、底層原理、常用接口和適用場景等方面詳細解析:

一、核心特性

  1. 雙向鏈表結構
    每個節點包含:

    • 數據域(存儲元素值)
    • 前驅指針(指向當前節點的前一個節點)
    • 后繼指針(指向當前節點的后一個節點)
      首節點的前驅指針和尾節點的后繼指針均為?nullptr,不形成循環。
  2. 高效的插入與刪除

    • 在任意位置(頭部、尾部、中間)插入或刪除元素的時間復雜度為?O(1)(只需修改相鄰節點的指針,無需移動其他元素)。
    • 但查找目標位置需要遍歷鏈表,時間復雜度為?O(n),因此 “查找 + 插入 / 刪除” 的整體復雜度為 O (n)。
  3. 不支持隨機訪問
    無法通過下標([])直接訪問元素,必須從首節點或尾節點開始遍歷(通過迭代器?++/--?移動),訪問第 n 個元素的時間復雜度為 O (n)(這是與?vectordeque?的核心區別)。

  4. 內存動態分配
    元素在堆上逐個分配內存,節點間無需連續,因此不會像?vector?那樣因擴容導致大規模內存拷貝,但存在額外的指針內存開銷(每個節點兩個指針)。

二、底層原理(為何插入刪除高效?)

list?的高效插入 / 刪除源于其鏈表結構:

  • 當已知插入 / 刪除位置的迭代器時,操作僅需 3 步:
    1. 創建新節點(插入時)或標記待刪除節點(刪除時);
    2. 修改前一個節點的后繼指針,指向新節點(插入)或下一個節點(刪除);
    3. 修改新節點(插入)或下一個節點的前驅指針,指向合適的節點。
  • 整個過程無需移動其他元素,僅涉及指針修改,因此效率極高。

例如,在節點?A?和?B?之間插入節點?C

原鏈表:A <-> B  
插入后:A <-> C <-> B  
(僅需修改 A 的后繼指針和 B 的前驅指針)

三、常用成員函數(核心接口)

list?提供了豐富的接口,尤其針對鏈表特性優化了插入、刪除和移動操作:

類別成員函數功能描述
構造 / 析構list()默認構造空鏈表
list(n, val)構造包含?n?個?val?的鏈表
list(beg, end)從迭代器范圍?[beg, end)?構造鏈表(如從?vector?或數組初始化)
兩端操作push_front(val)在頭部插入元素(O (1))
push_back(val)在尾部插入元素(O (1))
pop_front()刪除頭部元素(O (1),需確保鏈表非空)
pop_back()刪除尾部元素(O (1),需確保鏈表非空)
任意位置操作insert(pos, val)在迭代器?pos?指向的位置前插入?val,返回新元素的迭代器(O (1))
erase(pos)刪除迭代器?pos?指向的元素,返回下一個元素的迭代器(O (1))
erase(beg, end)刪除迭代器范圍?[beg, end)?內的元素,返回下一個元素的迭代器(O (n))
元素訪問front()獲取頭部元素的引用(O (1))
back()獲取尾部元素的引用(O (1))
鏈表操作clear()清空所有元素(O (n))
size()返回元素個數(O (1),C++11 后支持,之前版本需遍歷計數)
empty()判斷是否為空(O (1))
sort()對鏈表排序(內部實現為歸并排序,O (n log n),不支持?std::sort?因為需要隨機訪問迭代器)
reverse()反轉鏈表(O (n))
splice(pos, list2)將鏈表?list2?的所有元素移動到當前鏈表?pos?位置前(O (1),無元素拷貝)

下面是list容器特有的操作及其示例,所有操作將在同一段代碼中展示:

#include <iostream>
#include <list>
#include <algorithm>using namespace std;int main() {// 創建兩個鏈表list<int> list1 = {3, 1, 4, 1, 5};list<int> list2 = {2, 7, 1, 8};cout << "初始鏈表:" << endl;cout << "list1: ";for (int num : list1) cout << num << " ";  // 3 1 4 1 5cout << "\nlist2: ";for (int num : list2) cout << num << " ";  // 2 7 1 8cout << endl << endl;// 1. sort() - 鏈表排序list1.sort();cout << "1. list1排序后: ";for (int num : list1) cout << num << " ";  // 1 1 3 4 5cout << endl;// 2. unique() - 移除連續重復元素(需先排序)list1.unique();cout << "2. list1去重后: ";for (int num : list1) cout << num << " ";  // 1 3 4 5cout << endl;// 3. reverse() - 反轉鏈表list1.reverse();cout << "3. list1反轉后: ";for (int num : list1) cout << num << " ";  // 5 4 3 1cout << endl;// 4. merge() - 合并兩個已排序的鏈表(會修改原鏈表)list1.sort();  // 先確保list1有序list2.sort();  // 先確保list2有序list1.merge(list2);  // 合并到list1,list2會被清空cout << "4. 合并后list1: ";for (int num : list1) cout << num << " ";  // 1 1 2 3 4 5 7 8cout << "\n   合并后list2: ";for (int num : list2) cout << num << " ";  // 空cout << endl;// 5. splice() - 轉移元素(從另一個鏈表移動元素)list<int> list3 = {10, 20, 30};auto it = list1.begin();advance(it, 3);  // 移動迭代器到第4個元素位置list1.splice(it, list3, list3.begin(), list3.end());  // 將list3所有元素插入到list1的指定位置cout << "5. splice后list1: ";for (int num : list1) cout << num << " ";  // 1 1 2 10 20 30 3 4 5 7 8cout << "\n   splice后list3: ";for (int num : list3) cout << num << " ";  // 空cout << endl;// 6. remove() - 移除所有指定值的元素list1.remove(1);  // 移除所有值為1的元素cout << "6. 移除所有1后: ";for (int num : list1) cout << num << " ";  // 2 10 20 30 3 4 5 7 8cout << endl;// 7. remove_if() - 移除滿足條件的元素(例如移除偶數)list1.remove_if([](int n) { return n % 2 == 0; });cout << "7. 移除所有偶數后: ";for (int num : list1) cout << num << " ";  // 3 5 7cout << endl;return 0;
}

四、適用場景(什么時候用?list?)

list?適合以下場景:

  1. 頻繁在任意位置插入 / 刪除元素
    例如:實現鏈表式數據結構(如鄰接表)、日志系統(需在中間插入修正記錄)、 undo/redo 操作棧(頻繁在頭部插入歷史記錄)。

  2. 元素數量動態變化大,且無需隨機訪問
    當不需要通過下標訪問元素,僅需順序遍歷,且增刪操作頻繁時,list?比?vector(中間增刪效率低)和?deque(中間增刪效率低)更合適。

  3. 需要高效移動元素塊
    通過?splice?成員函數可以 O (1) 時間移動整個鏈表或子鏈表(無元素拷貝,僅修改指針),適合實現鏈表合并、拆分等操作。

五、與?vectordeque?的對比

特性listvectordeque
底層結構雙向鏈表連續動態數組分段數組 + 中控數組
隨機訪問([]不支持(O (n))支持(O (1))支持(O (1))
任意位置插入 / 刪除O (1)(已知位置)O (n)(需移動元素)O (n)(需移動元素)
內存連續性不連續連續分段連續
內存開銷高(節點含指針)低(僅存儲元素)中(分段管理)
迭代器類型雙向迭代器隨機訪問迭代器隨機訪問迭代器
適用場景頻繁任意位置增刪頻繁隨機訪問頻繁雙端操作 + 隨機訪問

六、使用示例(代碼演示)

#include <iostream>
#include <list>
#include <algorithm>  // 用于 find 等算法int main() {// 1. 構造 list 并初始化std::list<int> lst1;                      // 空鏈表std::list<int> lst2(3, 5);                // 3個5:[5,5,5]std::list<int> lst3(lst2.begin(), lst2.end());  // 從 lst2 復制:[5,5,5]// 2. 插入元素lst1.push_back(10);    // 尾部插入:[10]lst1.push_front(20);   // 頭部插入:[20,10]auto it = lst1.begin();  // it 指向 20++it;                    // it 指向 10lst1.insert(it, 30);    // 在 10 前插入 30:[20,30,10]// 3. 遍歷元素(只能通過迭代器或范圍 for)std::cout << "lst1 元素:";for (int val : lst1) {std::cout << val << " ";  // 20 30 10}std::cout << std::endl;// 4. 刪除元素lst1.pop_front();       // 刪除頭部:[30,10]it = std::find(lst1.begin(), lst1.end(), 30);  // 查找 30 的迭代器if (it != lst1.end()) {lst1.erase(it);     // 刪除 30:[10]}// 5. 鏈表特有操作std::list<int> lst4 = {3, 1, 2};lst4.sort();            // 排序:[1,2,3]lst4.reverse();         // 反轉:[3,2,1]std::cout << "lst4 排序反轉后:";for (int val : lst4) {std::cout << val << " ";  // 3 2 1}return 0;
}

七、注意事項

  1. 迭代器有效性list?的迭代器在插入元素后仍有效(只需調整指針,節點地址不變);刪除元素后,只有指向被刪除節點的迭代器失效,其他迭代器仍可使用(這是?list?的重要優勢)。
  2. 不支持?std::sortstd::sort?要求隨機訪問迭代器,而?list?是雙向迭代器,因此必須使用自身的?sort()?成員函數。
  3. 緩存不友好:由于元素內存不連續,CPU 緩存命中率低,遍歷速度通常慢于?vector(即使兩者時間復雜度均為 O (n))。

總之,list?是針對 “頻繁任意位置增刪” 優化的容器,在不需要隨機訪問的場景中,能顯著提升操作效率。

---------------------------------------------------------------------------------------------------------------------------------

deque插入(insert)的底層原理

通過__index判斷插入點位置,選擇移動元素更少的方向(頭部或尾部),體現 “短路徑優先” 的優化思想。這段代碼的注釋清晰展現了deque中間插入的優化邏輯,即通過巧妙利用頭尾操作的高效性,減少元素移動的數量,從而提升插入性能。

// 模板函數定義:在deque的中間位置插入單個元素的輔助函數
// 返回值:插入后新元素的迭代器
// 參數:__pos-插入位置迭代器;__x-要插入的元素值
template <class _Tp, class _Alloc>
typename deque<_Tp, _Alloc>::iterator
deque<_Tp,_Alloc>::_M_insert_aux(iterator __pos, const value_type& __x)
{// 計算插入點__pos相對于起始位置_M_start的偏移量(邏輯索引)// 用于判斷插入點更靠近頭部還是尾部difference_type __index = __pos - _M_start;// 復制要插入的元素(避免原元素被意外修改,確保值的穩定性)value_type __x_copy = __x;// 判斷插入點是否更靠近頭部(距離頭部比距離尾部近)// 采用"短路徑優先"策略,減少需要移動的元素數量if (size_type(__index) < this->size() / 2) {// 分支1:插入點靠近頭部,從頭部方向移動元素// 在頭部插入一個當前頭部元素的副本(利用deque頭部插入高效的特性)// 此時頭部會有一個重復元素,后續會通過移動覆蓋push_front(front());// 定義迭代器:__front1指向新插入的頭部副本元素iterator __front1 = _M_start;++__front1;// __front2指向__front1的下一個元素(原頭部元素)iterator __front2 = __front1;++__front2;// 重新定位插入點__pos:因頭部插入可能導致迭代器失效,通過索引重新計算__pos = _M_start + __index;// __pos1指向插入點的下一個元素(需要移動的起始位置)iterator __pos1 = __pos;++__pos1;// 將[__front2, __pos1)范圍內的元素復制到__front1開始的位置// 效果:從頭部方向將元素向后移動一個位置,為新元素騰出空間copy(__front2, __pos1, __front1);}else {// 分支2:插入點靠近尾部,從尾部方向移動元素// 在尾部插入一個當前尾部元素的副本(利用deque尾部插入高效的特性)// 此時尾部會有一個重復元素,后續會通過移動覆蓋push_back(back());// 定義迭代器:__back1指向新插入的尾部副本元素iterator __back1 = _M_finish;--__back1;// __back2指向__back1的前一個元素(原尾部元素)iterator __back2 = __back1;--__back2;// 重新定位插入點__pos:因尾部插入可能導致迭代器失效,通過索引重新計算__pos = _M_start + __index;// 將[__pos, __back2]范圍內的元素從后向前復制到__back1方向// 效果:從尾部方向將元素向后移動一個位置,為新元素騰出空間copy_backward(__pos, __back2, __back1);}// 在騰出的插入位置放入新元素的副本*__pos = __x_copy;// 返回指向新插入元素的迭代器return __pos;
}

需要注意的是: vector?的?insert?操作可能導致迭代器失效,這是由?vector?底層連續內存的特性決定的。當插入元素引發內存重新分配或元素移動時,原有的迭代器、指針或引用可能指向無效內存,使用它們會導致未定義行為(如程序崩潰、數據錯誤)。

如何避免迭代器失效?

  1. 使用?insert?的返回值更新迭代器
    vector::insert?會返回一個新的迭代器,指向插入的新元素。用這個返回值更新原迭代器,可避免失效:

    auto it = vec.begin() + 1;
    // 插入元素并獲取新迭代器
    it = vec.insert(it, 99);  // it 現在指向新插入的99,有效
    
  2. 提前預留足夠容量(reserve
    若已知插入元素的數量,先用?reserve(n)?預留足夠容量,避免插入時觸發擴容:

    vec.reserve(100);  // 預留100個元素的空間
    // 后續插入不超過100個元素時,不會觸發擴容
    
  3. 插入后重新獲取迭代器
    若無法提前預留容量,插入后通過索引或?begin()?重新計算迭代器:

    vec.insert(vec.begin() + 1, 99);
    auto it = vec.begin() + 1;  // 重新獲取,有效

總結

從這個表格中,我們可以了解到 C++ 標準庫中三種主要序列容器(vectordequelist)的接口特性和功能差異,主要信息如下:

1. 容器基本信息

  • 三種種容器對應的頭文件:vector對應<vector>deque對應<deque>list對應<list>
  • 這三種容器都屬于序列容器,遵循線性存儲結構。

2. 通用成員函數

三種容器都支持的核心操作(相同點):

  • 構造 / 析構:都有構造函數(constructor)和析構函數(destructor)
  • 賦值操作:都支持operator=(賦值運算符)和assign(批量賦值)。
  • 迭代器都支持begin/end(正向迭代器)、rbegin/rend(反向迭代器),以及帶c前綴的常量迭代器(如cbegin/cend)。
  • 元素訪問:都支持front(訪問首元素)和back(訪問尾元素)。
  • 容器屬性:都支持empty(判斷是否為空)、size(當前元素數量)、max_size(最大可容納元素數)、resize(調整容器大小)。
  • 修改操作:都支持clear(清空容器)、insert(插入元素)、emplace(原位構造元素)、erase(刪除元素)、push_back(尾部插入)、emplace_back(尾部原位構造)、pop_back(尾部刪除)、swap(交換容器內容)。
  • 內存分配器:都支持get_allocator(獲取內存分配器)。

3. 容器特有差異

三種容器的獨特接口(不同點):

  • vector

    • 支持at(帶邊界檢查的下標訪問)和operator[](下標訪問)。
    • 支持data(直接獲取底層數據指針)。
    • capacity(當前容量)、reserve(預留容量)、shrink_to_fit(收縮容量至實際大小),體現其連續內存的特性。
    • 不支持頭插
  • deque

    • 支持atoperator[](下標訪問),但無data(非連續內存)。
    • 支持shrink_to_fit(C++11 后)。
  • list(雙向鏈表):

    • 不支持下標訪問(無atoperator[]data)。
    • 支持push_front(頭部插入)、emplace_front(頭部原位構造)、pop_front(頭部刪除),且效率很高(鏈表特性)。
    • 專屬操作merge(合并鏈表)、splice(轉移元素)、remove(按值刪除)、remove_if(按條件刪除)、reverse(反轉鏈表)、unique(去重)、sort(排序),這些都是鏈表結構優化的操作。

4. 容器選擇依據

從接口差異可推斷適用場景:

  • vector:適合隨機訪問頻繁、尾部增刪為主的場景(連續內存,隨機訪問效率 O (1))。
  • deque:適合頭尾兩端頻繁增刪的場景(雙端隊列,兩端操作效率 O (1))。
  • list:適合任意位置頻繁插入 / 刪除的場景(鏈表結構,增刪效率 O (1),但隨機訪問效率低 O (n))。

這個表格本質上是三種容器接口兼容性功能獨特性的對比,幫助開發者根據需求選擇合適的容器。

刪除重復元素

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

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

相關文章

Time-MOE添加MLP分類頭進行分類任務

文章目錄一、背景&#xff1a;Time-MoE 的 4096 長度限制二、數據準備&#xff08;以帕金森二分類為例&#xff09;三、標簽對齊&#xff08;弱監督&#xff09;四、類別不平衡 & 數據劃分五、模型微調&#xff08;凍結 backbone&#xff0c;只訓 MLP 頭&#xff09;六、評…

樸素貝葉斯:用 “概率思維” 解決分類問題的經典算法

一、貝葉斯&#xff1a;從 “逆概” 問題走來的數學家要理解樸素貝葉斯&#xff0c;得先回到它的 “源頭”—— 貝葉斯公式&#xff0c;以及它要解決的核心問題&#xff1a;逆概問題。1. 貝葉斯的 “生不逢時”托馬斯?貝葉斯&#xff08;Thomas Bayes&#xff0c;約 1701-1761…

Qt/C++開發監控GB28181系統/視頻點播主碼流子碼流/動態切換碼流/支持海康大華/全網唯一

一、前言說明 目前市面上的國標監控系統&#xff0c;沒有看到可以切換碼流的&#xff0c;都是默認主碼流&#xff0c;包括easynvr、livegbs、wvp等&#xff0c;很是奇怪為什么他們不做呢&#xff1f;難道沒有用戶反饋需要這個&#xff1f;我這就遇到過一些用戶需要能夠切換主碼…

【 MYSQL | 基礎篇 四大SQL語句 】資料位于文章末尾

摘要&#xff1a;本文先介紹數據庫 SQL 的核心概念&#xff0c;接著闡述 SQL 通用語法與 DDL、DML、DQL、DCL 四大分類&#xff0c;隨后詳細講解各類語句操作&#xff0c;包括 DDL 的數據庫與表操作及數據類型&#xff0c;DML 的數據增刪改&#xff0c;DQL 的查詢語法與功能&am…

Webrtc支持FFMPEG硬解碼之Intel

Intel QSV下載編譯git clone https://github.com/lu-zero/mfx_dispatch.git1.使用CMake生產VS工程編譯生成libmfx.lib文件 頭文件為mfx文件夾libmfx---include---mfx---lib---libmfx.libWebrtc中ffmpeg的修改因為Webrtc中的ffmpeg是使用gn進行編譯的&#xff0c;所以這里先找到…

【二叉樹(DFS) - LeetCode】437. 路徑總和 III

437. 路徑總和 III 題解&#xff1a;DFS /*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* TreeNode() : val(0), left(nullptr), right(nullptr) {}* TreeNode(int x) : val(x), left(nullp…

【Python】shutil.make_archive() 方法詳解

文章目錄功能概述函數簽名核心參數詳解1. base_name2. format3. root_dir4. base_dir使用示例將 /home/user/project/data 目錄打包為 data.tar.gz&#xff0c;并保存到 /home/user/backups/打包當前工作目錄下的 docs 文件夾為 zip 文件替代方案總結shutil.make_archive() 是 …

CAN總線(Controller Area Network Bus)控制器局域網總線(二)

6、錯誤幀 總線上所有設備都會監督總線的數據&#xff0c;一旦發現“位錯誤”或“填充錯誤”或“CRC錯誤”或“格式錯誤”或“應答錯誤” &#xff0c;這些設備便會發出錯誤幀來破壞數據&#xff0c;同時終止當前的發送設備。7、過載幀 當接收方收到大量數據而無法處理時&#…

LeetCode 317 離建筑物最近的距離

LeetCode 317 題的詳細題目信息如下&#xff1a;題目名稱Shortest Distance from All Buildings&#xff08;中文譯名&#xff1a;離建筑物最近的距離&#xff09;題目描述給你一個由 0、1 和 2 組成的二維網格&#xff0c;其中&#xff1a;0 代表空地1 代表建筑物2 代表障礙物…

AI之CodeTool之Kode:Kode(claude_code風格)的簡介、安裝和使用方法、案例應用之詳細攻略

AI之CodeTool之Kode&#xff1a;Kode(claude_code風格)的簡介、安裝和使用方法、案例應用之詳細攻略 目錄 相關文章 LLMs之PE之SystemPrompt&#xff1a;analysis_claude_code的簡介、使用方法、案例應用之詳細攻略 AI之CodeTool之Kode&#xff1a;Kode(claude_code風格)的簡…

網絡請求優化:用 Retrofit 攔截器玩轉日志、重試與緩存,OkHttp 和 Volley 誰更香?

目錄 1. 攔截器:Retrofit 的“超級管理員” 攔截器的本質 為什么用攔截器? 2. 日志攔截器:讓請求和響應“現原形” 引入日志攔截器 實現日志攔截器 日志輸出示例 生產環境注意事項 3. 重試攔截器:網絡不穩定也能穩如狗 設計重試邏輯 集成到 Retrofit 優化重試策…

LeetCode - 283. 移動零

題目 283. 移動零 - 力扣&#xff08;LeetCode&#xff09; 思路 我們使用左右兩個指針&#xff1a;左指針left指向已處理好的非零元素的末尾位置&#xff0c;右指針right用于遍歷數組。 算法步驟&#xff1a; 初始化left為-1&#xff08;表示還沒有處理任何非零元素&…

Redis不同場景下的注意事項

Redis常見的 使用場景&#xff1a; 緩存系統(核心場景) 存儲熱點數據&#xff0c;減少數據庫訪問壓力。提升接口響應速度。技術點&#xff1a; 用String/Hash 存儲結構化數據結合過期時間&#xff08;TTL&#xff09;和緩存淘汰策略(如LRU)管理內存。解決緩存問題&#xff1a;穿…

【完整源碼+數據集+部署教程】高速公路施工區域物體檢測系統源碼和數據集:改進yolo11-RepNCSPELAN

背景意義 隨著城市化進程的加快&#xff0c;高速公路建設與維護工作日益頻繁&#xff0c;施工區域的安全管理成為亟待解決的重要問題。在高速公路施工區域&#xff0c;工人和設備的安全是首要考慮因素&#xff0c;而有效的物體檢測系統能夠顯著提高施工現場的安全性與工作效率。…

如何在FastAPI中玩轉全鏈路追蹤,讓分布式系統故障無處遁形?

url: /posts/30e1d2fbf1ad8123eaf0e1e0dbe7c675/ title: 全鏈路追蹤如何讓FastAPI微服務架構的每個請求都無所遁形? date: 2025-08-28T23:40:47+08:00 lastmod: 2025-08-28T23:40:47+08:00 author: cmdragon summary: 全鏈路追蹤是現代微服務架構中監控系統行為的核心技術,通…

Win11 壓縮實測:Win11 的壓縮軟件的最佳配置和使用方式

文章目錄測試環境機器配置被壓縮文件WinRAR7zipLinux子系統準備極限壓縮減小字典的極限壓縮7zipWin11準備極限壓縮7zip系統內置右鍵壓縮菜單極限壓縮總結&#xff1a;Win11 的壓縮軟件的最佳配置和使用方式測試環境 機器配置 Win11系統 16GB內存 8核CPU 被壓縮文件 文件夾內…

CMake構建學習筆記22-libxml2庫的構建

在上一篇文章《CMake構建學習筆記21-通用的CMake構建腳本》中&#xff0c;筆者封裝了一個通用的cmake構建腳本cmake-build.ps1&#xff0c;那么這里筆者就嘗試通過這個腳本來構建libxml2庫。 libxml2是GNOME項目下的XML庫&#xff0c;雖然比不上TinyXML-2輕量&#xff0c;但是…

虛擬私有網絡筆記

VPN應用場景 ——VPN概述 ? 利用公共網絡來構建的私人專用網絡稱為虛擬私有網絡&#xff08;VPN&#xff0c; Virtual Private Network&#xff09;&#xff0c;用于構建VPN的公共網絡包括Internet 、幀中繼、ATM等。在公共網絡上組建的VPN象企業現有的私有網絡 一樣提供安全性…

Python 輕量級 HTML 解析器 - lxml入門教程

文章目錄初始化解析器路徑查找查找所有標簽查找指定 id 的標簽查找指定 class 的標簽查找包含指定 class 的標簽復雜路徑查找示例1示例2常見操作獲取所有標簽的鏈接獲取 div 標簽的文本內容, 其他標簽類似其他元素操作初始化解析器 from lxml import html from lxml.html impor…

(CVPR-2025)VideoMage:文本生成視頻擴散模型的多主體與動作定制化

VideoMage&#xff1a;文本生成視頻擴散模型的多主體與動作定制化 paper title&#xff1a;VideoMage: Multi-Subject and Motion Customization of Text-to-Video Diffusion Models paper是National Taiwan University發表在CVPR 2025的工作 Code:鏈接 圖1. 多主體與動作定制化…