1. 程式人生 > 其它 >C++ ——常用STL容器

C++ ——常用STL容器

技術標籤:演算法——資料結構c++stl

摘要

vector 變長陣列,倍增的思想

pair 儲存二元組

string 字串,substr(), c_str()

queue 佇列, push(),pop(),front()

priority_queue, 優先佇列,push(),pop(),top()

deque,雙端佇列

stack 棧, push(),pop(),top()

set,map,multiset,multimap, 基於平衡二叉樹(紅黑樹),動態維護有序序列

unordered_set, unordered_map, unordered_multiset,unordered_multimap,

雜湊表

bitset, 壓位

vector

基礎應用

#include <vector>

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <vector>

using namespace std;

int main()
{
    vector<int> a(n); //定義一個長度為n的int陣列
    vector<int> a(10,1); //定義一個長度為10的int陣列,並把每個元素初始化為1
    vecotor<int> a[10]; //定義一個vector陣列(10個vector)
    
    for(auto x : a) cout << x << endl;  //遍歷陣列中的元素

    a.size(); //返回vector中元素的個數
    a.empty(); //a是否為空,若為空,返回true,否則,返回false
    a.clear(); //清空

    return 0;
}

size(); //返回vector中元素的個數

empty(); //a是否為空,若為空,返回true,否則,返回false

clear(); //清空

front(); //返回第一個元素

back(); //返回最後一個元素

push_back() / pop_back() //向vector末尾插入一個元素/把vecor最後一個元素刪除

迭代器 begin(); //vecor 的第0個元素 end(); //vecor的最後一個元素的後面一個元素

a.begin() = a[0]; a.end() = a[a.size()];

[] :vector支援隨機定址,和陣列一樣

黑科技

支援比較運算,按字典序來比較兩個vecor大小

int main()
{
    vector<int> a(4,3),b(3,4);
    if(a < b) puts("a < b");

    return 0;
}
//輸出: a < b 

size()和empty()所有容器都有,時間複雜度為O(1);

clear()函式並不是所有容器都有,queue 沒有;

auto可以遍歷所有容器。

倍增思想:自動變長,減少申請的次數。

系統為某一個程式分配空間時,所需時間基本上與空間大小無關,而只與申請次數有關

三種遍歷方法

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <vector>

using namespace std;

int main()
{
    vector<int> a;

    for(int i = 0; i < 10; i ++ ) a.push_back(i);

    //下標遍歷
    for(int i = 0; i < a.size(); i++ ) cout << a[i] << ' ';
    cout << endl;

    //迭代器遍歷
    for(vector<int> :: iterator i = a.begin(); i != a.end(); i ++ )
    cout << *i << ' ';
    cout << endl;

    //範圍遍歷(程式碼短,效率高)
    for(auto x : a) cout << x << ' ';
    cout << endl;

    return 0;
}

輸出樣例:

注:auto 用於總動推斷變數型別

例如上述程式碼,vector<int> :: iterator 也可以寫成 auto.

pair

用於儲存一個二元組

可以看做幫我們實現了一個結構體,而且自帶比較函式

定義方法:

pair< , >前後兩個變數型別可以任意

例如:pair<int,string> p;

構造pair(初始化):

p = make_pair(10,"abc");

或C ++ 11 中可以直接寫成 :p = {10,"abc"};

基礎應用:

p.first : 取pair的第一個元素;

p.second : 取pair的第二個元素

pair 支援比較運算,以first為第一關鍵字,以second為第二關鍵字(字典序)

常用情景:

某個東西有兩種不同的屬性,我們就可以用一個pair來存,可能用到某種屬性來排序,這時我們把要排序的關鍵字放到first裡,把不需要排序的關鍵字放到second裡,直接對pair排序就可以了。

假如某個東西有三種屬性,也可以用pair來存哦!這時我們可以用兩次pair,下面以int為例。

pair<int,pair<int,int>> p;

那麼可以通過巢狀的方式儲存任意多個。

string

C++把字串進行了封裝

基礎應用

支援size(),empty(),clear()

length()作用與size()相同,都是返回字串長度

可以在一個字串末尾加上字串或字元

int main()
{
    string a = "abc";

    a += "def";
    a += "g";
  
    cout << a << endl;
    cout << a.substr(1,2) << endl;
    printf("%s/n",a.c_str());
    //用printf輸出一個string,要輸出字元陣列的起始地址

    return 0;
}
//輸出:
// abcdefg
// bc
// abcdefg

substr(引數1,引數2); 返回某個子串

引數1:下標起始位置; 引數2:子串長度

當第二個引數很大,超出字串長度時,就會輸出到最後一個字串為止

也可以把第二個引數省略,就會直接返回從起始位置開始到末尾的整個子串。

c_str() 返回string儲存字串的起始地址

queue佇列

基礎應用

#include <queue>

支援size(),empty();

push() 向隊尾插入一個元素

pop()彈出隊頭元素

front()返回隊頭元素

back()返回隊尾元素

queue不支援clear()函式,若要清空,重新構造一個空的佇列就可以了

int main()
{
    queue<int> q;

    q = queue<int> ();

    return 0;
}

priority_queue 優先佇列(堆)

基礎應用

支援size(),empty()

不支援cear()

push() 向堆中插入一個元素

top() 返回堆頂元素

pop()彈出堆頂元素

定義的堆預設為大根堆

那麼定義小根堆方法:

1.直接插入負數(-x從大到小,x就是從小到大的)

2.

int main()
{
    //大根堆
    priority_queue <int> heap;

    //小根堆
    priority_queue <int,vector<int>,greater<int>> heap;
    
    return 0;
}

stack 棧

基礎應用

支援size(),empty()

不支援clear()函式

push() 向棧頂插入一個元素

top()返回棧頂元素

pop()彈出棧頂元素

deque 雙端佇列

一個加強版的vector

很NB,但缺點是速度比較慢,效率低

支援size(),empty(),clear()

front(),back(),push_back(),pop_back()上面已經介紹過,這裡不再多說了。

push_front() 向隊首插入一個元素

pop_front() 從隊首彈出一個元素

[ ] : 支援隨機定址

begin() / end() 迭代器

set,map,multiset,multimap, 基於平衡二叉樹(紅黑樹),動態維護有序序列

支援size(),empty(),clear() 時間複雜度O(1)

增刪改查的操作 時間複雜度 為 O(logn)

begin(),end() 支援++ -- 返回前驅和後繼

set/multiset

#include <set>

定義

set<int>S;

multiset<int>MS;

基礎應用

set 中不能有重複元素,如果我們插入了重複的元素,這個操作就會被忽略掉。

multiset中可以有重複元素。

下面所有操作的時間複雜度都是log(n)

二者均支援的操作:

insert() 插入一個元素

find() 查詢一個元素,若不存在,返回end()迭代器

count() 返回某個元素的個數 (當然,set中只有0和1兩種情況,multiset中有幾個就返回幾個)

erase():

1.輸入是一個數x,則刪除所有x;(mutiset中可能存在多個x) 時間複雜度O(k + log(n)) k是x的個數

2.輸入是一個迭代器,則刪除這個迭代器;

核心操作

lower_bound() / upper_bound()

lower_bound(x) 返回大於等於 x 的最小的數的迭代器

upper_bound(x) 返回大於x的最小的數的迭代器

若不存在返回 end()

map / multimap

#include<map>

map容器是一個鍵值對key-value的對映,其內部實現是一棵以key為關鍵碼的紅黑樹。Map的key和value可以是任意型別,其中key必須定義小於號運算子。

宣告

map<key_type, value_type> name;

例如:

map<long, long, bool> vis;

map<string, int> hash; //把string對映到int

map<pair<int, int>, vector<int>> test;

size/empty/clear/begin/end均與set類似。

Insert/erase

與set類似,但其引數均是pair<key_type, value_type>。

基礎應用

insert() 輸入的引數是一個pair

erase() 輸入的引數是pair 或 迭代器 都可以

支援find() ,lower_bound() / upper_bound()

核心操作

[ ] 可以像用陣列一樣用map

時間複雜度是O(logn)

int main()
{
    map<string,int> a;
    
    a["abc"] = 1;

    cout << a["abc"] << endl;

    return 0;
}

//輸出 1

unordered_set, unordered_map, unordered_multiset,unordered_multimap, 雜湊表

#include <unordered_xxx>

和上面類似,增刪改查的時間複雜度是O(1)

缺點:不支援lower_bound() / upper_bound()函式(內部是無序的), 迭代器的 ++ -- (凡是和排序有關的操作都是不支援的)

bitset, 壓位

例如:開一個長度為1024的bool陣列需要1024位元組=1kb(C ++ 中bool陣列是1位元組),如果我們把它壓到每一位中,沒一個位元組存八位,那麼就只需要開128個位元組,比正常的bool陣列省八倍記憶體,使用的空間是正常bool陣列的1/8。

再例如:如果我們想存一個10000*10000 的bool矩陣,需要10^{8}個bool,大概是100MB的空間,而題目的空間限制是64MB,小於100MB,這個時候我們用bitset來存就只需要12MB就可以了。

定義:

bitset<10000> S; <>裡不是型別而是個數,這一點與前面的容器不同。

基礎應用

支援各種位運算操作 ~ , & , | , ^

移位操作 >> , <<

== , !=

[ ] 取出某一位是0還是1

count() 返回有多少個1

any() 判斷至少有一個1

none() 判斷是否全為0

set() 把所有位置1

set(k,v) 將第k為變成v

reset() 把所有位置0

flip() 等價於 ~(把所有位取反)

flip(k) 把第k位取反