資料結構——關聯容器

曉dawn發表於2020-10-25

一、關聯容器定義

關聯容器支援高效的關鍵字查詢和訪問。兩個主要的關聯容器(associative container)型別是map和set
map中的元素是一些關鍵字-值(key-value)對:關鍵字起到索引的作用,值則表示與索引相關聯的資料。
set中每個元素只包含一個關鍵字:set支援高效的關鍵字查詢操作——即檢查一個給定關鍵字是否在set中。
在某些文字處理的過程中,可以用一個set來儲存想要忽略的單詞。而字典則是一個很好的使用map的例子:可以將單詞視為關鍵字,將單詞釋義視為值。
在STL中提供了8個關聯容器,這8個容器間的不同體現在3個維度上
(1)每個容器或者是set,或者是map;
(2)每個容器要麼要求關鍵字不重複,要麼允許關鍵字重複,允許重複關鍵字的容器名字中包含單詞multi;
(3)每個容器中的元素要麼按順序儲存(使用紅黑樹組織),要麼無序儲存(使用雜湊函式組織),不保持關鍵字按順序儲存的容器名字中包含單詞unordered。
因此,8個關聯容器為:
(1)map;
(2)set;
(3)multimap;
(4)multiset;
(5)unordered_map;
(6)unordered_set;
(7)unordered_multimap;
(8)unordered_multiset。
map和multimap定義在標頭檔案map中,set和multiset定義在標頭檔案set中,unordered_map和unordered_multimap定義在標頭檔案unordered_map中,unordered_set和unordered_multiset定義在標頭檔案unordered_set中。

map型別通常稱為關聯陣列,關聯陣列與正常的陣列很類似,不同之處在於其下標不必是整數,而可以通過字串等型別的關鍵字作為下標進行資料查詢。

關聯容器的迭代器都是雙向的
關聯容器可用於只讀取元素的演算法。但是很多這類演算法都需要搜尋序列。由於關聯容器中的元素不能通過它們的關鍵字進行(快速)查詢,因此對其使用泛型搜尋演算法幾乎總是不好的,因為泛型find演算法會進行順序搜尋。而使用關聯容器定義的專用find成員函式會比呼叫泛型find函式快得多
map和unordered_map容器提供了下標運算子和對應的at函式,用來獲取元素。而set型別不支援下標操作。
如果我們所關心的只是一個特定元素是否在容器中,可能使用find成員函式是最佳選擇。對於不允許重複關鍵字的容器,使用find還是count沒什麼區別,但對於允許重複關鍵字的容器,使用count成員函式會做更多的工作,其如果元素在容器中,還會統計有多少個元素有相同的關鍵字。所以,如果不需要計數,最好使用find函式。

二、有序關聯容器

有序容器使用比較函式來比較關鍵字,從而將元素按順序儲存。預設情況下,比較操作是採用關鍵字型別的<運算子。
STL中的lower_bound和upper_bound查詢函式不適用於無序容器。
如果一個multimap或multiset中有多個元素具有給定的關鍵字,則這些元素在容器中是相鄰儲存的。此時可以參照以下示例進行查詢:

string search_item("Alain de Botton"); // 要查詢的作者
auto entries = authors.count(search_item); // 元素的數量
auto iter = authors.find(search_item); // 此作者的第一本書
// 用一個迴圈來查詢作者的所有著作
while (entries) {
    cout << iter->second << endl;
    ++iter;
    --entries;
}

// 還可以使用lower_bound和upper_bound來處理
for (auto beg = authors.lower_bound(search_item), end = authors.upper_bound(search_item); beg != end; ++beg) {
    cout << beg->second << endl;
}
// 此方法更直接

set是按特定順序儲存唯一元素的容器。其模板類定義為:
template < class T, class Compare = less, class Alloc = allocator<‘T’>> class set
其成員函式包括:
(1)(constructor),set構造器;
(2)(destructor),set銷燬器;
(3)operator=,複製構造器;
(4)empty(),測試容器是否為空;
(5)size(),返回set的元素個數;
(6)max_size(),返回容器所能儲存的最多元素個數,其取決於庫的內部實現,但儘管如此,其也不保證一定能持有上述值所說的那麼多個元素;
(7)insert(),通過插入新的元素來擴充套件容器,如果要插入的元素已經存在於容器中,則不再進行插入,並返回該元素在容器中位置的迭代器;
(8)erase(),從容器中按照指定要求移除元素;
(9)swap(),互動2個set中所有的元素內容;
(10)clear(),清空set中所有元素內容,使其size=0;
(11)emplace(),類似於insert(),但不是對給定值進行復製作為新元素,而是直接使用其引數,呼叫元素的建構函式,直接構造一個新元素;
(12)emplace_hint(),emplace()的加強版,使用給定的提示資訊作為插入位置的參考,可提高插入速度;
(13)key_comp(),用於確定set中元素儲存順序的函式,set按照該函式處理結果,進行元素排序;
(14)value_comp(),對於set而言,和key_comp()完全等價;
(15)find(),返回指定值在set中找到位置的迭代器,時間複雜度為O(logN);
(16)count(),返回set中指定值存在的個數;
(17)lower_bound(),返回指定值在set中第一次出現位置的迭代器,時間複雜度為O(logN);
(18)upper_bound(),返回指定值在set中最後一次出現位置的迭代器,時間複雜度為O(logN);
(19)equal_range(),返回指定值在set中出現範圍的迭代器對,時間複雜度為O(logN)。

multiset是按特定順序儲存元素的容器,其中多個元素可以具有相等的值。其模板類定義為:
template < class T, class Compare = less, class Alloc = allocator<‘T’>> class multiset
其成員函式包括:
(1)(constructor),multiset構造器;
(2)(destructor),multiset銷燬器;
(3)operator=,複製構造器;
(4)empty(),測試容器是否為空;
(5)size(),返回multiset的元素個數;
(6)max_size(),返回容器所能儲存的最多元素個數,其取決於庫的內部實現,但儘管如此,其也不保證一定能持有上述值所說的那麼多個元素;
(7)insert(),通過插入新的元素來擴充套件容器,如果要插入的元素已經存在於容器中,則不再進行插入,並返回該元素在容器中位置的迭代器;
(8)erase(),從容器中按照指定要求移除元素;
(9)swap(),互動2個multiset中所有的元素內容;
(10)clear(),清空multiset中所有元素內容,使其size=0;
(11)emplace(),類似於insert(),但不是對給定值進行復製作為新元素,而是直接使用其引數,呼叫元素的建構函式,直接構造一個新元素;
(12)emplace_hint(),emplace()的加強版,使用給定的提示資訊作為插入位置的參考,可提高插入速度;
(13)key_comp(),用於確定multiset中元素儲存順序的函式,multiset按照該函式處理結果,進行元素排序;
(14)value_comp(),對於multiset而言,和key_comp()完全等價;
(15)find(),返回指定值在multiset中找到第一次出現位置的迭代器,時間複雜度為O(logN);
(16)count(),返回multiset中指定值存在的個數;
(17)lower_bound(),返回指定值在multiset中第一次出現位置的迭代器,時間複雜度為O(logN);
(18)upper_bound(),返回指定值在multiset中最後一次出現位置的迭代器,時間複雜度為O(logN);
(19)equal_range(),返回指定值在multiset中出現範圍的迭代器對,時間複雜度為O(logN)。

map是關聯容器,按照特定的順序儲存由鍵和對映值組成的元素。其模板類定義為:
template < class Key, class T, class Compare = less, class Alloc = allocator<pair<const Key,T> > class map
其成員函式包括:
(1)(constructor),map構造器;
(2)(destructor),map銷燬器;
(3)operator=,複製構造器;
(4)empty(),測試容器是否為空;
(5)size(),返回map的元素個數;
(6)max_size(),返回容器所能儲存的最多元素個數,其取決於庫的內部實現,但儘管如此,其也不保證一定能持有上述值所說的那麼多個元素;
(7)operator[],將指定的關鍵字作為索引來獲取在map中對應的值,如果該關鍵字已在map中,則返回其對應的值,如果不在,則執行insert()操作,插入該鍵值對;
(8)at(),類似於operator[],只不過當該關鍵字不在map中,不是執行insert()操作,而是丟擲範圍錯誤;
(9)insert(),通過插入新的元素來擴充套件容器,如果要插入的元素已經存在於容器中,則不再進行插入,並返回該元素在容器中位置的迭代器;
(10)erase(),從容器中按照指定要求移除元素;
(11)swap(),互動2個map中所有的元素內容;
(12)clear(),清空map中所有元素內容,使其size=0;
(13)emplace(),類似於insert(),但不是對給定值進行復製作為新元素,而是直接使用其引數,呼叫元素的建構函式,直接構造一個新元素;
(14)emplace_hint(),emplace()的加強版,使用給定的提示資訊作為插入位置的參考,可提高插入速度;
(15)key_comp(),用於確定map中元素儲存順序的函式,map按照該函式處理結果,進行元素排序;
(16)value_comp(),用於確定map中元素儲存順序的函式;
(17)find(),返回指定值在map中找到位置的迭代器,時間複雜度為O(logN);
(18)count(),返回map中指定值存在的個數;
(19)lower_bound(),返回指定值在map中第一次出現位置的迭代器,時間複雜度為O(logN);
(20)upper_bound(),返回指定值在map中最後一次出現位置的迭代器,時間複雜度為O(logN);
(21)equal_range(),返回指定值在map中出現範圍的迭代器對,時間複雜度為O(logN)。

multimap是關聯容器,按照特定的順序儲存由鍵和對映值組成的元素,其中多個元素可以具有相等的關鍵字。其模板類定義為:
template < class Key, class T, class Compare = less, class Alloc = allocator<pair<const Key,T> > class multimap
其成員函式包括:
(1)(constructor),multimap構造器;
(2)(destructor),multimap銷燬器;
(3)operator=,複製構造器;
(4)empty(),測試容器是否為空;
(5)size(),返回multimap的元素個數;
(6)max_size(),返回容器所能儲存的最多元素個數,其取決於庫的內部實現,但儘管如此,其也不保證一定能持有上述值所說的那麼多個元素;
(7)insert(),通過插入新的元素來擴充套件容器,如果要插入的元素已經存在於容器中,則不再進行插入,並返回該元素在容器中位置的迭代器;
(8)erase(),從容器中按照指定要求移除元素;
(9)swap(),互動2個multimap中所有的元素內容;
(10)clear(),清空multimap中所有元素內容,使其size=0;
(11)emplace(),類似於insert(),但不是對給定值進行復製作為新元素,而是直接使用其引數,呼叫元素的建構函式,直接構造一個新元素;
(12)emplace_hint(),emplace()的加強版,使用給定的提示資訊作為插入位置的參考,可提高插入速度;
(13)key_comp(),用於確定multimap中元素儲存順序的函式,multimap按照該函式處理結果,進行元素排序;
(16)value_comp(),用於確定multimap中元素儲存順序的函式;
(17)find(),返回指定值在multimap中找到第一次出現位置的迭代器,時間複雜度為O(logN);
(18)count(),返回multimap中指定值存在的個數;
(19)lower_bound(),返回指定值在multimap中第一次出現位置的迭代器,時間複雜度為O(logN);
(20)upper_bound(),返回指定值在multimap中最後一次出現位置的迭代器,時間複雜度為O(logN);
(21)equal_range(),返回指定值在multimap中出現範圍的迭代器對,時間複雜度為O(logN)。

三、無序關聯容器

無序關聯容器不是使用比較運算子來組織元素,而是使用一個雜湊函式和關鍵字型別的==運算子在關鍵字型別的元素沒有明顯的序關係的情況下,無序容器非常有用。另外當維護元素的序代價很高時,無序容器也很有用。
無序容器在儲存上組織為一組桶,每個桶儲存零個或多個元素。無序容器使用一個雜湊函式將元素對映到桶。為了訪問一個元素,容器首先計算元素的雜湊值,它指出應該搜尋哪個桶。容器將具有一個特定雜湊值的所有元素都儲存在相同的桶中。因此,無序容器的效能依賴於雜湊函式的質量和桶的數量和大小
計算一個元素的雜湊值和在桶中搜尋都是很快的操作。但如果一個桶中儲存了很多元素,那麼查詢一個特定元素就需要大量比較操作。
無序容器提供了一組管理桶的函式,這些成員函式允許我們查詢容器的狀態以及在必要時強制容器進行重組。
我們不能直接定義關鍵字型別為自定義類型別的無序容器,預設的雜湊函式不支援這些型別,需要提供自定義的hash模板函式
無論在有序容器還是無序容器中,具有相同關鍵字的元素都是相鄰儲存的

unordered set是不按特定順序儲存唯一元素的容器,允許根據元素的值快速檢索單個元素。其模板類定義為:
template < class Key, class Hash = hash, class Pred = equal_to, class Alloc = allocator<‘Key’>> class unordered_set
其成員函式包括:
(1)(constructor),unordered set構造器;
(2)(destructor),unordered set銷燬器;
(3)operator=,複製構造器;
(4)empty(),測試容器是否為空;
(5)size(),返回unordered set的元素個數;
(6)max_size(),返回容器所能儲存的最多元素個數,其取決於庫的內部實現,但儘管如此,其也不保證一定能持有上述值所說的那麼多個元素;
(7)find(),返回指定值在unordered set中找到位置的迭代器,時間複雜度為O(1);
(8)count(),返回unordered set中指定值存在的個數;
(9)equal_range(),返回指定值在unordered set中出現範圍的迭代器對,時間複雜度為O(1);
(10)emplace(),類似於insert(),但不是對給定值進行復製作為新元素,而是直接使用其引數,呼叫元素的建構函式,直接構造一個新元素;
(11)emplace_hint(),emplace()的加強版,使用給定的提示資訊作為插入位置的參考,可提高插入速度;
(12)insert(),通過插入新的元素來擴充套件容器,如果要插入的元素已經存在於容器中,則不再進行插入,並返回該元素在容器中位置的迭代器;
(13)erase(),從容器中按照指定要求移除元素;
(14)swap(),互動2個unordered set中所有的元素內容;
(15)clear(),清空unordered set中所有元素內容,使其size=0;
(16)bucket_count(),返回容器的桶的個數,桶的數量直接影響裝填因子的大小,容器會自動增加桶的數量,以維持裝填因子低於某個閾值水平,來維持雜湊表的效能;
(17)max_bucket_count(),返回容器所能儲存的最多桶的個數;
(18)bucket_size(),返回容器中指定索引的桶中元素的個數;
(19)bucket(),返回容器中指定的關鍵字對應的桶索引;
(20)load_factor(),返回當前容器的裝填因子大小;
(21)max_load_factor(),返回容器的裝填因子的最大水平;
(22)rehash(),設定容器內桶的個數為指定值或更多,如果指定值超過當前容器水平,容器將重新進行雜湊,即所有現有元素的索引將全部打亂重建;
(23)reserve(),設定容器內桶的數量為最適合指定值的水平,如果指定值超過當前容器水平,容器將重新進行雜湊;
(24)hash_function(),返回當前容器所使用的雜湊函式物件;
(25)key_eq(),返回當前容器所使用的比較條件。

unordered multiset是不按特定順序儲存唯一元素的容器,允許根據元素的值快速檢索單個元素,但可以有多個元素具有相同的值。其模板類定義為:
template < class Key, class Hash = hash, class Pred = equal_to, class Alloc = allocator<‘Key’>> class unordered_multiset
其成員函式包括:
(1)(constructor),unordered multiset構造器;
(2)(destructor),unordered multiset銷燬器;
(3)operator=,複製構造器;
(4)empty(),測試容器是否為空;
(5)size(),返回unordered multiset的元素個數;
(6)max_size(),返回容器所能儲存的最多元素個數,其取決於庫的內部實現,但儘管如此,其也不保證一定能持有上述值所說的那麼多個元素;
(7)find(),返回指定值在unordered multiset中找到第一次出現位置的迭代器,時間複雜度為O(1);
(8)count(),返回unordered multiset中指定值存在的個數;
(9)equal_range(),返回指定值在unordered multiset中出現範圍的迭代器對,時間複雜度為O(1);
(10)emplace(),類似於insert(),但不是對給定值進行復製作為新元素,而是直接使用其引數,呼叫元素的建構函式,直接構造一個新元素;
(11)emplace_hint(),emplace()的加強版,使用給定的提示資訊作為插入位置的參考,可提高插入速度;
(12)insert(),通過插入新的元素來擴充套件容器,如果要插入的元素已經存在於容器中,則不再進行插入,並返回該元素在容器中位置的迭代器;
(13)erase(),從容器中按照指定要求移除元素;
(14)swap(),互動2個unordered multiset中所有的元素內容;
(15)clear(),清空unordered multiset中所有元素內容,使其size=0;
(16)bucket_count(),返回容器的桶的個數,桶的數量直接影響裝填因子的大小,容器會自動增加桶的數量,以維持裝填因子低於某個閾值水平,來維持雜湊表的效能;
(17)max_bucket_count(),返回容器所能儲存的最多桶的個數;
(18)bucket_size(),返回容器中指定索引的桶中元素的個數;
(19)bucket(),返回容器中指定的關鍵字對應的桶索引;
(20)load_factor(),返回當前容器的裝填因子大小;
(21)max_load_factor(),返回容器的裝填因子的最大水平;
(22)rehash(),設定容器內桶的個數為指定值或更多,如果指定值超過當前容器水平,容器將重新進行雜湊,即所有現有元素的索引將全部打亂重建;
(23)reserve(),設定容器內桶的數量為最適合指定值的水平,如果指定值超過當前容器水平,容器將重新進行雜湊;
(24)hash_function(),返回當前容器所使用的雜湊函式物件;
(25)key_eq(),返回當前容器所使用的比較條件。

unordered map是不按特定順序儲存元素的容器,其儲存由關鍵字和對映值組成的元素,並允許基於鍵快速檢索單個元素。其模板類定義為:
template < class Key, class T, class Hash = hash, class Pred = equal_to, class Alloc = allocator< pair<const Key,T> >class unordered_map
其成員函式包括:
(1)(constructor),unordered map構造器;
(2)(destructor),unordered map銷燬器;
(3)operator=,複製構造器;
(4)empty(),測試容器是否為空;
(5)size(),返回unordered map的元素個數;
(6)max_size(),返回容器所能儲存的最多元素個數,其取決於庫的內部實現,但儘管如此,其也不保證一定能持有上述值所說的那麼多個元素;
(7)operator[],將指定的關鍵字作為索引來獲取在unordered map中對應的值,如果該關鍵字已在unordered map中,則返回其對應的值,如果不在,則執行insert()操作,插入該鍵值對;
(8)at(),類似於operator[],只不過當該關鍵字不在unordered map中,不是執行insert()操作,而是丟擲範圍錯誤;
(9)find(),返回指定值在unordered map中找到位置的迭代器,時間複雜度為O(1);
(10)count(),返回unordered map中指定值存在的個數;
(11)equal_range(),返回指定值在unordered map中出現範圍的迭代器對,時間複雜度為O(1);
(12)emplace(),類似於insert(),但不是對給定值進行復製作為新元素,而是直接使用其引數,呼叫元素的建構函式,直接構造一個新元素;
(13)emplace_hint(),emplace()的加強版,使用給定的提示資訊作為插入位置的參考,可提高插入速度;
(14)insert(),通過插入新的元素來擴充套件容器,如果要插入的元素已經存在於容器中,則不再進行插入,並返回該元素在容器中位置的迭代器;
(15)erase(),從容器中按照指定要求移除元素;
(16)swap(),互動2個unordered map中所有的元素內容;
(17)clear(),清空unordered map中所有元素內容,使其size=0;
(18)bucket_count(),返回容器的桶的個數,桶的數量直接影響裝填因子的大小,容器會自動增加桶的數量,以維持裝填因子低於某個閾值水平,來維持雜湊表的效能;
(19)max_bucket_count(),返回容器所能儲存的最多桶的個數;
(20)bucket_size(),返回容器中指定索引的桶中元素的個數;
(21)bucket(),返回容器中指定的關鍵字對應的桶索引;
(22)load_factor(),返回當前容器的裝填因子大小;
(23)max_load_factor(),返回容器的裝填因子的最大水平;
(24)rehash(),設定容器內桶的個數為指定值或更多,如果指定值超過當前容器水平,容器將重新進行雜湊,即所有現有元素的索引將全部打亂重建;
(25)reserve(),設定容器內桶的數量為最適合指定值的水平,如果指定值超過當前容器水平,容器將重新進行雜湊;
(26)hash_function(),返回當前容器所使用的雜湊函式物件;
(27)key_eq(),返回當前容器所使用的比較條件。

unordered multimap是不按特定順序儲存元素的容器,其儲存由關鍵字和對映值組成的元素,並允許基於鍵快速檢索單個元素,可以有多個元素具有相同的鍵。其模板類定義為:
template < class Key, class T, class Hash = hash, class Pred = equal_to, class Alloc = allocator< pair<const Key,T> >class unordered_multimap
其成員函式包括:
(1)(constructor),unordered multimap構造器;
(2)(destructor),unordered multimap銷燬器;
(3)operator=,複製構造器;
(4)empty(),測試容器是否為空;
(5)size(),返回unordered multimap的元素個數;
(6)max_size(),返回容器所能儲存的最多元素個數,其取決於庫的內部實現,但儘管如此,其也不保證一定能持有上述值所說的那麼多個元素;
(7)find(),返回指定值在unordered multimap中找到第一次出現位置的迭代器,時間複雜度為O(1);
(8)count(),返回unordered multimap中指定值存在的個數;
(9)equal_range(),返回指定值在unordered multimap中出現範圍的迭代器對,時間複雜度為O(1);
(10)emplace(),類似於insert(),但不是對給定值進行復製作為新元素,而是直接使用其引數,呼叫元素的建構函式,直接構造一個新元素;
(11)emplace_hint(),emplace()的加強版,使用給定的提示資訊作為插入位置的參考,可提高插入速度;
(12)insert(),通過插入新的元素來擴充套件容器,如果要插入的元素已經存在於容器中,則不再進行插入,並返回該元素在容器中位置的迭代器;
(13)erase(),從容器中按照指定要求移除元素;
(14)swap(),互動2個unordered multimap中所有的元素內容;
(15)clear(),清空unordered multimap中所有元素內容,使其size=0;
(16)bucket_count(),返回容器的桶的個數,桶的數量直接影響裝填因子的大小,容器會自動增加桶的數量,以維持裝填因子低於某個閾值水平,來維持雜湊表的效能;
(17)max_bucket_count(),返回容器所能儲存的最多桶的個數;
(18)bucket_size(),返回容器中指定索引的桶中元素的個數;
(19)bucket(),返回容器中指定的關鍵字對應的桶索引;
(20)load_factor(),返回當前容器的裝填因子大小;
(21)max_load_factor(),返回容器的裝填因子的最大水平;
(22)rehash(),設定容器內桶的個數為指定值或更多,如果指定值超過當前容器水平,容器將重新進行雜湊,即所有現有元素的索引將全部打亂重建;
(23)reserve(),設定容器內桶的數量為最適合指定值的水平,如果指定值超過當前容器水平,容器將重新進行雜湊;
(24)hash_function(),返回當前容器所使用的雜湊函式物件;
(25)key_eq(),返回當前容器所使用的比較條件。

相關文章