map和hash_map
list支持快速的插入和刪除,但是查找費(fèi)時(shí);
vector支持快速的查找,但是插入費(fèi)時(shí)。
map查找的時(shí)間復(fù)雜度是對(duì)數(shù)的,這幾乎是最快的,hash也是對(duì)數(shù)的。?
如果我自己寫,我也會(huì)用二叉檢索樹,它在大部分情況下可以保證對(duì)數(shù)復(fù)雜度,最壞情況是常數(shù)復(fù)雜度,而std::map在任何情況下都可以保證對(duì)數(shù)復(fù)雜度,原因是它保證存諸結(jié)構(gòu)是完全二叉檢索樹,但這會(huì)在存諸上犧牲一些時(shí)間。
STL?? 中的?? map?? 內(nèi)部是平衡二叉樹,所以平衡二叉樹的性質(zhì)都具備。查找數(shù)據(jù)的時(shí)間也是對(duì)數(shù)時(shí)間。?vector,在分配內(nèi)存上一般要比?? new?? 高效的多。
為什么說?? hash_map?? 是對(duì)數(shù)級(jí)的?在不碰撞的情況下,hash_map是所有數(shù)據(jù)結(jié)構(gòu)中查找最快的,它是常數(shù)級(jí)的。?
如果對(duì)問題設(shè)計(jì)了足夠好的hash算法,保證碰撞率很低,hash_map的查找效率無可置疑。?
另外,STL的map,它的查找是對(duì)數(shù)級(jí)的,是除hash_map外最高的了,你可以說“也許還有改進(jìn)余地”,但對(duì)于99.9999%的程序員,設(shè)計(jì)一個(gè)比STL?? map好的map,我執(zhí)悲觀態(tài)度。?
STL的map有平衡策略(比如紅黑樹什么的),所以不會(huì)退化,不需要考慮數(shù)據(jù)本身的分布問題。只不過,如果數(shù)據(jù)本身是排好序的,用vector或heap會(huì)明顯的快些,因?yàn)樗鼈兊脑L問比較簡單。
我想沒必要懷疑stl::map的查找效率,影響效率最主要的因素是什么?算法,在查找問題上,有什么算法比RB_tree更好嗎?至少現(xiàn)在還沒有。不否 認(rèn)你可以通過自己寫代碼,設(shè)計(jì)一個(gè)符合你需要的BR—TREE,比stl::map簡捷那么一點(diǎn),但最多也就每次迭代中少一行指令而已,處理十萬個(gè)數(shù)據(jù)多 執(zhí)行十萬行指令,這對(duì)你重要嗎?如果你不是在設(shè)計(jì)OS像LINUX,沒人會(huì)關(guān)注這十萬行指令花的時(shí)間。?
rb-tree的時(shí)間花在了插入和刪除上,如果你不是對(duì)插入和刪除效率要求很高,你沒有理由不選擇基于rb-tree的stl::map。
大多數(shù)程序員寫不出比std::map更好的map,這是當(dāng)然的。然而并不是std::map的所有特性都出現(xiàn)在我們的程序中,自己編寫的可以更適合自己的程序,的確會(huì)比std::map更快一些。
關(guān)于hash_map,它與map的實(shí)現(xiàn)機(jī)制是不一樣的,map內(nèi)部一般用樹來實(shí)現(xiàn),其查找操作是O(logN)的,這個(gè)沒有爭議,我就不多說了。?
hash_map的查找,內(nèi)部是通過一個(gè)從key到value的運(yùn)算函數(shù)來實(shí)現(xiàn)的,這個(gè)函數(shù)“只接受key作為參數(shù)”,也就是說,hash_map的查找 算法與數(shù)據(jù)量無關(guān),所以認(rèn)為它是O(1)級(jí)的。來這里的應(yīng)該都是達(dá)人,可以參看《數(shù)據(jù)結(jié)構(gòu)》。當(dāng)然,事實(shí)總不這樣完美,再引一段前面我自已說的話,進(jìn)一步 說明,以免誤會(huì):
-----------------------------------------?
在不碰撞的情況下,hash_map是所有數(shù)據(jù)結(jié)構(gòu)中查找最快的,它是常數(shù)級(jí)的。?
------------------------------------------?
注意我的前提:“在不碰撞的情況下”,其實(shí)換句話說,就是要有足夠好的hash函數(shù),它要能使key到value的映射足夠均勻,否則,在最壞的情況下,它的計(jì)算量就退化到O(N)級(jí),變成和鏈表一樣。?
如果說?? hash_map?? 是所有容器中最慢的,也只能說:“最拙劣的hash函數(shù)”會(huì)使hash_map成為查找最慢的容器。但這樣說意義不大,因?yàn)?#xff0c;最湊巧的排列能使冒泡排序成為最快的排序算法。
BS: "對(duì)于大型容器而言,hash_map能夠提供比map快5至10倍的元素查找速度是很常見的,尤其是在查找速度特別重要的地方.另一方面,如果hash_map選擇了病態(tài)的散列函數(shù),他也可能比map慢得多. "
ANSIC++在1998年之后就沒再有重大改變,并且決定不再向C++標(biāo)準(zhǔn)庫中做任何重大的變更,正是這個(gè)原因,hash?? table(包括hash_map)并沒有被列入標(biāo)準(zhǔn)之中,雖然它理應(yīng)在C++標(biāo)準(zhǔn)之中占有一席之地。?
雖然,現(xiàn)在的大多數(shù)編譯平臺(tái)支持hash?? table,但從可移植性方面考慮,還是不用hash?? table的好。
hehe俺也來湊湊熱鬧。?
1.有的時(shí)候vector可以替代map?
比如key是整數(shù),就可以以key的跨度作為長度來定義vector。?
數(shù)據(jù)規(guī)模很大的時(shí)候,差異是驚人的。當(dāng)然,空間浪費(fèi)往往也驚人。?
2.hash是很難的東西?
沒有高效低碰撞的算法,hash_xxx沒有意義。?
而對(duì)不同的類型,數(shù)據(jù)集,不可能有優(yōu)良的神仙算法。必須因場合而宜。?
俺有的解決方法是GP,可不是飯型,是遺傳編程,收效不錯(cuò)。
你的百萬級(jí)的數(shù)據(jù)放到vector不大合適。因?yàn)関ector需要連續(xù)的內(nèi)存空間,顯然在初始化這個(gè)容器的時(shí)候會(huì)花費(fèi)很大的容量。?
使用map,你想好了要為其建立一個(gè)主鍵嗎?如果沒有這樣的需求,為什么不考慮deque或者list??
map默認(rèn)使用的是deque作為容器。其實(shí)map不是容器,拿它與容器比較意義不大。因?yàn)槟憧梢耘渲盟牡讓尤萜黝愋汀?/span>
如果內(nèi)存不是考慮的問題。用vector比map好。map每插入一個(gè)數(shù)據(jù),都要排序一次。所以速度反不及先安插所有元素,再進(jìn)行排序。
用 binary_search對(duì)已序區(qū)間搜索,如果是隨機(jī)存取iterator,則是對(duì)數(shù)復(fù)雜度??梢?#xff0c;在不考慮內(nèi)存問題的情況下,vector比map 好。
如果你需要在數(shù)據(jù)中間進(jìn)行插入,list 是最好的選擇,vector?? 的插入效率會(huì)讓你痛苦得想死。
涉及到查找的話用map比較好,因?yàn)閙ap的內(nèi)部數(shù)據(jù)結(jié)構(gòu)用rb-tree實(shí)現(xiàn),而用vector你只能用線性查找,效率很低。
stl還提供了 hash容器,理論上查找是飛快~~~。做有序插入的話vector是噩夢,map則保證肯定是按key排序的,list要自己做些事情。
HASH類型的查找肯定快,是映射關(guān)系嘛,但是插入和刪除卻慢,要做移動(dòng)操作, LIST類型的使鏈?zhǔn)疥P(guān)系,插入非???#xff0c;但是查找卻費(fèi)時(shí),需要遍歷~~ , 還是用LIST類型的吧,雖然查找慢點(diǎn),
先快速排序,然后二分查找,效率也不低
總結(jié)
以上是生活随笔為你收集整理的map和hash_map的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: SQLite、MySQL和Postgre
- 下一篇: Mybase到期 破解