C++ STL hash表用法


C++ STL unordered_map用法

在C++11中,unordered_map作為一種關聯容器,替代了hash_map,unordered_map的底層實現是hash表,所以被稱為無序關聯容器。
不管是map還是unordered_map都是一種 key-map(value) 映射的容器,提供非常高的查找效率,下面我們來了解unordered_map的用法。

預備知識

在講解unordered_map之前,我們先得了解一些預備知識:

元素類型

除常用的語言內置類型以外,unordered_map的元素類型大致有以下幾種:

  • value_type : unordered_map元素類型,這種類型的形式為 key-map類型,key和map的類型都是模板類型。
  • key_type : key,模板類型
  • mapped_type :map,即我們常說的value,模板類型
  • pair類型 :pair類型也是STL中的常用類型,原型為template <class T1, class T2> struct pair;由於unordered_map使用的就是Key-Map匹配對,所以在這里使用比較多。

概念

  • 插槽:英文為bucket,又可以翻譯成桶。在hash表中,hash函數通常返回一個整型(或無符號整型)元素,對應hash表的數組下標,但是數組類型通常為指針指向一片內存或者是一個鏈表頭,對應許多元素,就像一個桶可以裝很多元素,這里稱為插槽。

構造函數

explicit unordered_map ( size_type n = N,const hasher& hf = hasher(),const key_equal& eql = key_equal(),const allocator_type& alloc = allocator_type() );  

這個構造函數接受無參數構造

  • n:為hash表的最小插槽數,如果未指定,將會被自動確定(取決於特定的庫實現,並不固定)
  • hf:hash函數,因為底層實現是hash表,必然就有hash函數,STL提供了非常全面的不同類型的hash函數實現,也可以自己實現hash函數。
  • key_equal:判斷兩個key對象的hash值相等以確定查找的命中,STL提供了大部分的不同類型的key_equal實現,同樣也可以實現hash函數
  • alloc:容易使用的內存構造器,可選擇不同的內存構建方式

explicit unordered_map ( const allocator_type& alloc );

指定unordered_map的構造器


template <class InputIterator>
unordered_map ( InputIterator first, InputIterator last,size_type n = N,const hasher& hf = hasher(),const key_equal& eql = key_equal(),const allocator_type& alloc = allocator_type() );  

接收輸入迭代器構造方式,將迭代器指向的元素區間進行復制構造


unordered_map ( const unordered_map& ump );
unordered_map ( const unordered_map& ump, const allocator_type& alloc );  

復制構造,第二個可指定構造器


unordered_map ( unordered_map&& ump );
unordered_map ( unordered_map&& ump, const allocator_type& alloc );  

移動構造方式,這個C++11中新支持的特性,移動構造方式提供臨時變量的引用,即右值引用的功能,&表示左值引用,&&表示右值引用。


unordered_map ( initializer_list<value_type> il,size_type n = N,const hasher& hf = hasher(),const key_equal& eql = key_equal(),const allocator_type& alloc = allocator_type() );  

以傳入列表的形式構造

示例:
std::unordered_mapstd::string,std::string strmap( {{"name","downey"},{"age","500"}} );


成員函數

at()

mapped_type& at ( const key_type& k );
const mapped_type& at ( const key_type& k ) const;  

根據Key值查找容器內元素,並返回map元素的引用。

示例:

std::unordered_map<std::string,int> mymap={"key",111};
map.at("key")=123;
map.at("key")+=123;

begin()

iterator begin() noexcept;
const_iterator begin() const noexcept;
local_iterator begin ( size_type n );
const_local_iterator begin ( size_type n ) const;  

指向容器內第一個元素的迭代器。迭代器訪問元素時,it->first對應key,it->second對應map(value).

end()

iterator end() noexcept;
const_iterator end() const noexcept;
local_iterator end (size_type n);
const_local_iterator end (size_type n) const;  

指向容器內最后一個元素的后一個位置的迭代器。

bucket()

size_type bucket ( const key_type& k ) const;  

以key值尋找元素在容器中的位置。

示例:

str_map map1;
map1.insert({"downey","hello"});   
cout<<map1.bucket (it->first)<<endl;
output:
2  

從返回值可以看出,即使是插入的第一個元素,位置也不一定是1,這跟容器的hash實現相關。

bucket_count()

size_type bucket_count() const noexcept;  

返回hash表的插槽值個數,這個函數的值對應構造函數中的n(最小插槽數)參數。

max_bucket_count()

size_type max_bucket_count() const noexcept;  

返回容器所能支持的最大插槽數,根據平台不同而不同,一般是一個非常大的數字。

bucket_size()

size_type bucket_size ( size_type n ) const;  

這個函數返回每個插槽中的元素數量。

cbegin()

const_iterator cbegin() const noexcept;
const_local_iterator cbegin ( size_type n ) const;  

返回const類型的第一位置迭代器

cend()

返回const類型的最后一個位置的下一位置的迭代器。

clear()

void clear() noexcept;

刪除容器內所有元素。

count()

size_type count ( const key_type& k ) const;  

某個key值對應的map(value)值的數量,因為unordered_map不允許重復元素,所以返回值總是0或1

emplace()

template <class... Args>
pair<iterator, bool> emplace ( Args&&... args );  

如果key元素是唯一的,在unordered_map中插入新元素,使用Args作為元素構造函數的參數來構造這個新元素。參數為右值引用。
示例:
mymap.emplace ("NCC-1701", "J.T. Kirk");
即可插入相應的map元素

emplace_hint()

template <class... Args>
iterator emplace_hint ( const_iterator position, Args&&... args );  

與emplace()操作一致,position參數則是提供一個建議搜索位置的起點的提示,可以優化執行時間。

empty()

bool empty() const noexcept;  

判斷容器是否為空,返回bool值

erase()

iterator erase ( const_iterator position );
size_type erase ( const key_type& k );
iterator erase ( const_iterator first, const_iterator last );  

根據不同的索引擦除插槽中的元素.

find()

iterator find ( const key_type& k );
const_iterator find ( const key_type& k ) const;  

查找函數,通過key查找一個元素,返回迭代器類型。

get_allocator()

allocator_type get_allocator() const noexcept;  

返回容器目前使用的內存構造器。

hash_function()

hasher hash_function() const;  

獲取hash容器當前使用的hash函數

insert()

pair<iterator,bool> insert ( const value_type& val );  

直接插入元素類型,返回pair類型,返回值pair第一元素是插入元素迭代器,第二元素表示操作是否成功

template <class P>
pair<iterator,bool> insert ( P&& val );  

移動插入方式,可以傳入右值插入
iterator insert ( const_iterator hint, const value_type& val );

用戶給出一個插入起點以優化查找時間
template
iterator insert ( const_iterator hint, P&& val );
template
void insert ( InputIterator first, InputIterator last );

復制型插入,將(first,last]所包含的內容全部復制插入
void insert ( initializer_list<value_type> il );
插入一個列表形式的元素

key_eq()

key_equal key_eq() const;  

獲取key equal函數,key_equal函數為判斷key值是否匹配,在一般情況下,hash函數並不能保證每一個輸入對應一個獨一無二的輸出,可能多個輸入會對應同一個輸出,這就是hash沖突。可能一個槽內同時由多個元素,這時候就需要使用key_equal來進行進一步判斷。

load_factor()

float load_factor() const noexcept;  

load factor在中文中被翻譯成負載因子,負載因子是容器中元素數量與插槽數量之間的比例。即:

load_factor = size / bucket_count 

max_load_factor()

float max_load_factor() const noexcept;
void max_load_factor ( float z );  

第一個函數是查詢目前容器最大的負載因子,默認為1。

第二個函數是進行最大的負載因子的設置。

max_size()

size_type max_size() const noexcept;  

容器可支持的元素最大數量,linux平台下,使用4.8.5的STL庫中這個值是:268435455

'='運算符重載

unordered_map& operator= ( const unordered_map& ump );
unordered_map& operator= ( unordered_map&& ump );
unordered_map& operator= ( intitializer_list<value_type> il );  

以不同方式對容器進行賦值。

'[]'操作符重載

mapped_type& operator[] ( const key_type& k );
mapped_type& operator[] ( key_type&& k );

[]操作符重載,使得容易可以通過map[Key]的方式進行索引。

rehash()

void rehash( size_type n );  

重建hash表,將插槽的數量擴展的n,如果n小於目前插槽數量,這個函數並不起作用。

reserve()

void reserve ( size_type n );

將容器的插槽數設置成最適合n個元素的情況,這樣可以避免多次rehash和直接rehash空間的浪費。

與rehash相比,這個函數由用戶給一個插槽數量建議值,由系統去分配空間,而rehash則是指定容器的插槽值

size()

size_type size() const noexcept;  

返回當前容器中元素的個數

swap()

void swap ( unordered_map& ump )  

交換兩個容器的內容,兩個容器的類型必須一致,但大小可以不同。

好了,關於C++ STL unordered_map 的API的用法討論就到此為止啦,如果朋友們對於這個有什么疑問或者發現有文章中有什么錯誤,歡迎留言

原創博客,轉載請注明出處!

祝各位早日實現項目叢中過,bug不沾身.


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM