C++ STL詳解(1)

2021-03-02 C和C加加

來源:blog.csdn.net/qq_41575507/article/details/113864734

概述

 STL 是「Standard Template Library」的縮寫,中文譯為「標準模板庫」。STL 是 C++ 標準庫的一部分,不用單獨安裝。

 C++ 對模板(Template)支持得很好,STL 就是藉助模板把常用的數據結構及其算法都實現了一遍,並且做到了數據結構和算法的分離。例如,vector 的底層為順序表(數組),list 的底層為雙向鍊表,deque 的底層為循環隊列,set 的底層為紅黑樹,hash_set 的底層為哈希表。

 STL 從根本上講是「容器」的集合,也是組件的集合。容器包括 list、vector、set、map 等;組件包括迭代器等。STL 的目的是標準化組件。

 STL 是 C++ 的一部分,不用額外安裝,被內建在支持 C++ 的編譯器中。

STL 的算法是標準算法,其實現了將已經定義好的算法應用在容器的對象上。

刷題時常用的STL

 通過概述可以了解到STL 就是藉助模板把常用的數據結構及其算法都實現了一遍,並且做到了數據結構和算法的分離。所以在刷題時配合使用 STL 可以極大的提高做題的速度。可以根據情況來選擇使用 STL 來做題目,如果題目對時間要求比較高的話可以不使用 STL,比如棧和隊列可以使用數組來進行模擬等等。一般情況下可以直接選擇使用STL來做題目。

vector初始化

.在定義時初始化vector的長度

 vector 可以一開始不定義大小,之後用 resize 方法分配大小,也可以一開始就定義大小,之後還可以對它插入刪除動態改變它的大小。不管在 main 函數裡還是在全局中定義,它都能夠直接將所有的值初始化為0 (不用顯式地寫出來,默認就是所有的元素為0)

注意:系統為某一程序分配空間時所需的時間與空間大小無關,而與分配的次數有關。所以儘量減少申請空間的次數,也有利於提到程序的效率。

 在vector的擴展大小中有一個 倍增思想:假如vector的實際長度為 n ,m為vector當前的最大長度,那麼在加入一個元素的時候,先看一下,假如當前的 n = m,則再動態申請一個 2m 大小的內存。反之,在刪除的時候,如果 n ≤ m ÷ 2 m\div2m÷2,則再釋放一半的內存。基於該思想,如果長度為 n 的vector數組,假設一開始只申請了一個空間,那麼最後其申請的次數是 l o g ( n ) log(n)log(n) 的,所以vector是一種效率比較高的數組。

#include<iostream>#include<vector>using namespace std;
int main() { vector<int> v(10); for (int i = 0; i < 10; i++) cout << v[i] << ' '; return 0;} 

#include<iostream>#include<vector>using namespace std;
int main() { vector<int> v(10, 9); for (int i = 0; i < 10; i++) cout << v[i] << ' '; return 0;}

#include<iostream>#include<vector>using namespace std;
int main() { vector<int> v[10]; int cnt = 1; for (int i = 0; i < 5; i++) { for (int j = 0; j < 5; j++) { v[i].push_back(cnt++); } } for (int i = 0; i < 5; i++) { for (int j = 0; j < 5; j++) { cout << v[i][j] << ' '; } cout << endl; }
return 0;}

#include<iostream>#include<vector>using namespace std;
int main() { vector<vector<int> > v; int cnt = 1; for (int i = 0; i < 5; i++) { vector<int> q; int x; cin >> x; while (x != -1) { q.push_back(x); cin >> x; } v.push_back(q); } cout << "輸出的結果為:" << endl; for (int i = 0; i < v.size(); i++) { for (int j = 0; j < v[i].size(); j++) { cout << v[i][j] << ' '; } cout << endl; }
return 0;}

size()

 size() :返回vector中元素的個數,時間複雜度 O(1)。

注意: 對於順序容器size() 的時間複雜度為 O(1),對於list之類的節點容器,可能是線性時間即 O(n)。所以在 for 循環中需要求長度時最好把 size() 放到循環之外求,這樣可以在一些情況下將算法的時間複雜度由 O(n 2 n^2n

2 ) 降到 O(n)。

#include<iostream>#include<vector>using namespace std;
int main() { vector<int> v(10, 9); cout << "數組中元素的個數為:" << v.size() << endl; int len = v.size(); for (int i = 0; i < len; i++) cout << v[i] << ' '; return 0;}

empty()

 empty() :v.empty() 檢查數組 v 是否為空。若容器為空則返回 true ,否則返回 false

push_back()

 向vector的最後插入一個元素

#include<iostream>#include<vector>using namespace std;
int main() { vector<int> v; v.push_back(1); v.push_back(2); v.push_back(3); for (int i = 0; i < 3; i++) cout << v[i] << ' '; return 0;}

pop_back()

 刪除vector的最後一個元素

#include<iostream>#include<vector>using namespace std;
int main() { vector<int> v; v.push_back(1); v.push_back(2); v.push_back(3); for (int i = 0; i < 3; i++) cout << v[i] << ' '; cout << endl; v.pop_back(); for (int i = 0; i < 3; i++) cout << v[i] << ' '; cout << endl; for (int i = 0; i < v.size(); i++) cout << v[i] << ' '; return 0;}

 通過以上實驗可知,使用 pop_back() 並不是真正的將最後一個元素刪除了,只是修改了vector的末尾指針。

clear()

 清空數組中的所有元素

#include<iostream>#include<vector>using namespace std;
int main() { vector<int> v; v.push_back(1); v.push_back(2); v.push_back(3); cout << "數組的元素個數為:" << v.size() << endl; for (int i = 0; i < v.size(); i++) cout << v[i] << ' '; cout << endl; v.clear(); cout << "數組的元素個數為:" << v.size(); return 0;}

front()、back()

 front()訪問vector的第一個元素,back() 返回最後一個元素。

#include<iostream>#include<vector>using namespace std;
int main() { vector<int> v; v.push_back(1); v.push_back(2); v.push_back(3); cout << "數組的第一個元素為:" << v.front() << endl; cout << "數組的最後一個元素為:" << v.back() << endl; return 0;}

begin()、end()

 begin() 返回指向容器首元素的迭代器。若容器為空,則返回的迭代器將等於 end() 。end() 返回指向容器末元素後一元素的迭代器,即指向vector中最後一個元素之後的一個元素。此元素表現為佔位符;試圖訪問它導致未定義行為。

operator[]

 vector支持隨機尋址,像數組一樣。operator[pos]返回位於指定位置 pos 的元素的引用。不進行邊界檢查。在上面的例子中已經用到很多次了,比如: v[i] 表示訪問vector中下標為 i 的元素。這裡就不再演示了。

vector的三種遍歷方式

使用隨機尋址的方式遍歷

範圍遍歷

迭代器方式遍歷

#include<iostream>#include<vector>using namespace std;
int main() { vector<int> v; for (int i = 0; i < 10; i++) v.push_back(i); for (int i = 0; i < v.size(); i++) cout << v[i] << ' '; cout << endl; for (int i : v) cout << i << ' '; cout << endl; for (vector<int>::iterator i = v.begin(); i != v.end(); i++) cout << *i << ' '; return 0;}

支持比較運算

 vector可以支持比較運算,可以直接比較兩個vector的大小。vector支持 ==, !=, <, <=, >, >= 運算符。

檢查兩個vector的內容是否相等,即它們是否擁有相同數量的元素且 vector1 中每個元素與 vector2 的同位置元素比較相等。

按 字典序 比較 vector1 與 vector2 的內容。

#include<iostream>#include<vector>using namespace std;
int main() { vector<int> a(6, 5), b(5, 6); if (a > b) cout << "a > b"; else cout << "b > a"; return 0;}

pair

 pair 是一個結構體模板,其可於一個單元存儲兩個相異對象。

定義方式

 pair 的定義方式為:pair<int, int>,其中的兩個參數可以是任意的,比如 int、string、double、float 等等。

初始化

 可以在定義pair的時候直接初始化pair。

#include<iostream>using namespace std;
int main() { pair<int, string> p(1, "AC-fun"); cout << p.first << ":" << p.second; return 0;}

構造pair

 pair 有兩種構造方式:

使用 make_pair() 創建一個 pair 對象,其類型根據各實參類型定義。

#include<iostream>using namespace std;
int main() { pair<int, string> p; p = make_pair(1, "AC-fun"); cout << p.first << ":" << p.second; return 0;}

在 C++ 11 中還可以直接構造。

#include<iostream>using namespace std;
int main() { pair<int, string> p; p = {1, "AC-fun"}; cout << p.first << ":" << p.second; return 0;}

訪問

 pair 以 first 為第一個關鍵字,以 second 為第二個關鍵字。例如現在已經構造好了一個 pair<int, string> p(1, "AC-fun"); 可以使用 p.first 訪問第一個關鍵字,使用 p.second 訪問第二個關鍵字。

#include<iostream>using namespace std;
int main() { pair<int, string> p(1, "AC-fun"); cout << p.first << ":" << p.second; return 0;}

支持比較運算

 pair 與 vector 一樣,也是可以支持比較運算的。pair支持 ==, !=, <, <=, >, >= 運算符。按照 字典序 進行排序。

嵌套pair

 如果有一種東西有三種屬性,可以使用嵌套的pair來存儲。比如:

pair<int, pair<int, string> >

stack

在開頭提到了可以使用數組模擬棧,這裡就只貼一下代碼。

使用數組模擬棧
#include<iostream>#include<string>using namespace std;
const int N = 100010;int stk[N], tt;
void add(int x) { stk[tt++] = x;}
void remove() { tt--;}
int top() { return stk[tt - 1];}
bool ept() { if (tt) return false; else return true;}
int main() { int n; cin >> n; while (n--) { string op; int x; cin >> op; if (op == "push") { cin >> x; add(x); } else if (op == "pop") { remove(); } else if (op == "empty") { if (ept()) { cout << "YES" << endl; } else { cout << "NO" << endl; } } else { cout << top() << endl; } }
return 0;}

queue

這裡就只貼一下數組模擬隊列的代碼。

使用數組模擬隊列

#include<iostream>#include<string>using namespace std;
const int N = 100010;int q[N], front, tail;
void add(int x) { q[tail++] = x;}
void remove() { front++;}
bool ept() { if (front == tail) return true; return false;}
int qey() { return q[front]; }
int main() { int n; cin >> n; while (n--) { string op; int x; cin >> op; if (op == "push") { cin >> x; add(x); } else if (op == "pop") { remove(); } else if (op == "empty") { if (ept()) cout << "YES" << endl; else cout << "NO" << endl; } else { cout << qey() << endl; } } return 0;}

未完待續~~~~~~~~

相關焦點

  • 跟我學C++中級篇——STL的學習
    一、c++標準庫C++的標準庫主要包含兩大類,首先是包含C的標準庫的,當然,為了適應c++對一些C庫進行了少許的修改和增加。最重要的當然是面向對象的c++庫;而c++庫又可以分成兩大類,即面向對象的c++庫和標準模板庫,也就是題目中的STL。
  • 跟我學C++中級篇——STL中的字符串
    二、字符串的實現在面試時經常有這種題,讓自己實現一個簡單的字符串類,下面是比較常見的實現的方式:class mystring{    public:         mystring() : str_(new char[1])         {            * str_ = '\0';         }
  • C 語言會比 C++ 快?
    這是在具有 100K 行的代碼庫上, 而我們的算法只有 1K 行代碼(當然我們的代碼中不包括 STL 雖然排除 STL 並不完全公平,但是加入 STL 計算代碼行也不完全公平,因為我們知道我們的算法完全可以在沒有任何 STL 依賴的情況下用 1K 行代碼來實現)。在編譯代碼時你會注意到 400 毫秒,即使它只有一個文件。
  • C++ initializer_list 詳解
    有了initializer_list之後,對於STL的container的初始化就方便多了,比如以前初始化一個vector需要這樣:std::vector v;v.push_back(1);v.push_back(2);v.push_back(3);v.push_back(4);
  • C++ STL詳解(4)
    但是要注意的是:這兩個是無序的,基於哈希表實現的,增刪改查的時間複雜度均為 O(1)。因為是無序的,所以不支持 lower_bound() 和 upper_bound() 以及迭代器的 ++、- -操作。unordered_set 中不允許有重複的元素,unordered_multiset 中允許有重複元素。
  • C++ vector詳解
    以下是正文前言本文mark了vector的一些接口,介紹了vector中的對內存和對象的管理詳解請見cppreference-vector。1. vector內部管理著一塊內存,壓入對象的時候,會使用這塊內部的內存使用placement new去進行對象的生成,而釋放對象的時候,顯式的去調用析構函數去釋放對象。2. size代表vector中的實際含有元素數量,而capacity表示容量。
  • 99%的工程師不知道的技巧,solidworks編輯stl文件
    今天solidworks家園給大家介紹Solidworks怎麼編輯stl文件 ,希望對大家有所幫助!1、 經常有人在群裡問我,Solidworks怎麼編輯stl文件(3D列印常用格式)?下圖是solidworks打開stl文件後的樣式,可以發現是無法編輯的,無法繪製草圖,甚至無法測量任何參數。
  • ​跟我學C++中級篇——STL的容器vector
    _Mylast;            _Move_backward_unchecked(_Whereptr, _Oldlast - 1, _Oldlast);            *_Whereptr = _STD move(_Obj._Storage.
  • SnappyHexMesh網格劃分實例詳解
    閱讀本文的前提是您已對blockMesh有一定的了解,否則建議提前閱讀《blockMesh網格劃分實例詳解》。圖1 snappyHexMesh工作流程[1]第一步:創建背景網格背景網格生成;在這一步通常使用blockMesh生成縱橫比(aspect ratio)約為1的六面體網格
  • C++ 的門門道道 | 技術頭條 - CSDN
    九、內存拷貝小心內存越界memcpy,memset有很強的限制,僅能用於POD結構,不能作用於stl容器或者帶有虛函數的類。帶虛函數的類對象會有一個虛函數表的指針,memcpy將破壞該指針指向。>十、用sprintf格式化字符串時,類型和格式化符號要嚴格匹配因為sprintf的函數實現裡是按格式化串從棧上取參數,任何不一致,都有可能引起不可預知的錯誤; /usr/include/inttypes.h裡定義了跨平臺的格式化符號,比如PRId64用于格式化int64_t十一、stl
  • C 2 C++進階篇(1)
    之前一直是對於面向過程的編程,python有過那種對象風格的編程,但是對於oop的實際開發還停留在表面,沒有獨立的開發c++經驗,也有好幾年沒有碰過c了。由於接手Qt的相關項目,所以對c to c++的進階希望能進行個自我總結。
  • python+C、C++混合編程的應用
    1、實驗一 使用冒泡程序驗證python和c/c++程序的性能差距python版冒泡程序:def bubble(arr,length): j = length - 1 while j >= 0: i = 0 while i < j:
  • 詳解 C++ STL 中 map::erase 的正確姿勢
    然而當想當然的在map::erase上照搬上面erase的用法時,就有問題了,查看http://www.cplusplus.com/reference/map/map/erase/ 上的說明:C++98(1)
  • 3D印表機教程 如何使用magics軟體修改STL格式文件
    我們從網絡上下載的3D列印模型一般也都是stl的,通過3D列印切片軟體處理後,即可輸出到3D列印進行列印。視頻教程連結:https://v.qq.com/x/page/r0793kr9uq8.html       小錦囊:      1、使用軟體:magics      2、在製作的過程中,主要使用的命令:標記面、分離被標記三角面片、標記殼體、合併零件、補洞模式、標籤。
  • c++的輸入與輸出
    c++輸入與輸出C++ 標準庫提供了一組豐富的輸入/輸出功能,本章將討論 C++ 編程中最基本和最常見的 I/O 操作。輸入輸出並不是c++語言的正式組成成分,c和c++沒有為輸入輸出提供專門的結構。在c語言中輸入輸出是通過調用scanf和printf 實現的,在c++中是通過調用流對象cin和cout實現的。
  • C++、java 和 C 的區別
    一、基礎類型c++:** java:** C#:1.以java為準,c++裡面的int short long 像這樣的整型 一般都有unsigned 和signed的區分 ,這個跟java和c# 的區別比較大,但c#裡面有unit ulong ushort 這三種就相當於c++的修飾詞unsigned,當c++李明的變量類型定義unsigned,就默認是整數。
  • 深入理解快速排序和 STL 的 sort 算法
    互換;步驟1-4:互換之後left指針從1開始向右掃描直到與right指針相遇,此時注意到pivot=3無右子序列且左子序列len=1,達到了遞歸循環的終止條件,此時可以認為由第一次循環產生的左子序列已經全部有序。
  • 「最佳實踐」C++陷阱與套路
    # 二、陷阱## 1.我的程序裡用了全局變量,為何進程退出會莫名其妙的core掉?sort算法對比較函數有很強的約束,不能亂來,如果要用,要自己提供比較函數或者函數對象,一定搞清楚什麼叫「嚴格弱排序」,一定要滿足以下3個特性:1. 非自反性2. 非對稱性3.