記錄下map 和unordered_map的用法
“ 多做善事才是好運的根本!”
2018年9月14日
8月、9月、10月~
挺過去,一切都會好的,
但是竭盡全力,
因為,你後悔不起~
記錄下C++、資料結構中的一些知識用法吧:
我們都知道,容器是存放資料的地方,常見的容器有序列式容器和關聯式容器,序列式容器,即其中的元素不一定有序,但可以被排序,比如vector、list、queue、stack、heap、priority_queue;而關聯式容器內部結構基本上是一個平衡二叉樹。所謂關聯,指每個元素都有一個鍵值和一個實值<key,value>,元素按照一定的規則存放。比如RB-tree、set、map、unordered_map、hashtable、hash_map、hash_set。
接下來著重介紹map和unordered_map:(用的最多)
map: #include <map>
unordered_map: #include <unordered_map>
算了,說一下map和set的區別吧,set:其內部元素會根據元素的鍵值自動被排序;區別於map,它的鍵值就是實值,而map可以同時擁有不同的鍵值和實值。
map:
一對一的方式來儲存資料,<關鍵字,對映值>,其內部通過R-B tree(紅黑樹)實現,而且會根據key值來自動將資料排序,因此map內部的所有元素都是有序的,紅黑樹的每一個節點都代表著map的一個元素。因此,對於map進行的查詢,刪除,新增等一系列的操作都相當於是對紅黑樹進行的操作。另外,map比hash_map(未進入stl)穩定,但是一般沒有hash_map快。其時間複雜度:O(log n)
unordered_map:
unordered_map底層用一個雜湊表(也叫散列表,通過把關鍵碼值對映到Hash表中一個位置來訪問記錄,查詢的時間複雜度可達到O(1),其在海量資料處理中有著廣泛應用)來實現。因此,其元素的排列順序是無序的。時間複雜度:O(1)常數級
明確下各自的優缺點:
map:
- 優點:
- 有序性,這是map結構最大的優點,其元素的有序性在很多應用中都會簡化很多的操作
- 紅黑樹,內部實現一個紅黑書使得map的很多操作在
lgn
的時間複雜度下就可以實現,因此效率非常的高
-
缺點: 空間佔用率高,因為map內部實現了紅黑樹,雖然提高了執行效率,但是因為每一個節點都需要額外儲存父節點、孩子節點和紅/黑性質,使得每一個節點都佔用大量的空間
-
適用處:對於那些有順序要求的問題,用map會更高效一些
unordered_map:
- 優點: 因為內部實現了雜湊表,因此其查詢速度非常的快
- 缺點: 雜湊表的建立比較耗費時間
- 適用處:對於查詢問題,
unordered_map
會更加高效一些,因此遇到查詢問題,常會考慮一下用unordered_map
舉例:(包括map的宣告、建立、遍歷)
leetcode 1兩數之和
/*
題目:leetcode 1 Two Sum 兩數之和
從給定的一組數中找到兩個數的和為target.返回兩個數的序號,假設每次輸入只有一組解
時間:2018年9月14日 12:16:34
思路:1.暴力搜尋,對於每個數去找後面和它的和為target的數,如果找到了就返回,時間複雜度O(n^2)
2.hash:先進行hash對映,<key,value>為 <nums[i], i>,對於每一個數,可以在O(1)的時間找到
即:用空間來彌補時間,建立使用一個HashMap,來建立數字和其下標位置之間的對映,也就是我求得一個數就直接能知道它的下標。
我們都知道HashMap是常數級的查詢效率,這樣,我們在遍歷陣列的時候,用target減去遍歷到的數字,就是另一個需要的數字了,
直接在HashMap中查詢其是否存在即可,注意要判斷查詢到的數字不是第一個數字,比如target是4,遍歷到了一個2,那麼另外一個2不能是之前那個2,
整個實現步驟為:先遍歷一遍陣列,建立HashMap對映,然後再遍歷一遍,開始查詢,找到則記錄index。
*/
#include <bits/stdc++.h>
using namespace std;
//法一:暴力搜尋
class Solution {
public:
vector<int> twoSum(vector<int> &num, int target) {
vector<int> v;
for(int i=0;i<num.size();++i)
{
for(int j=i+1;j<num.size();++j)
{
if(num[i]+num[j]==target)
{
v.push_back(i);
v.push_back(j);
break;
}
}
}
return v;
}
};
//法二:hash表
class Solution {
public:
vector<int> twoSum(vector<int> &num, int target) {
vector<int> v;
unordered_map<int,int> m;//宣告hash圖
for(int i=0;i<num.size();++i)//建立hash圖
{
m[num[i]]=i;
}
for(auto &it:m)//遍歷hash圖;
cout<<it.first<<" "<<it.second<<endl;
for(int i=0;i<num.size();++i)
{
int t=target-num[i];
if(m.count(t)&& m[t]!=i)//if(m.find(t)!=m.end()&&m[t]!=i)
{
v.push_back(i);
v.push_back(m[t]);
break;
}
}
return v;
}
};
int main()
{
vector<int> a={1,6,4,5,7};
Solution so;
vector<int> res;
res=so.twoSum(a,9);
for(auto i:res)//遍歷容器的簡單方法
cout<<i<<" ";
return 0;
}
一定要看懂,理解!
裡面的寫法很值得銘記。
最後,祝福所有努力的人,都會有好運!