仅靠“小于运算“生存的map
對于初學STL的人來說,map可能是最全能的伙伴,只需敲下三個字母,一個天然有序,方便擴展,高效檢索的數據結構就這樣輕輕松松的產生了,這得益于C++的模版技術。在享受標準模版庫帶給我們便利的同時,我們也需要簡單理解一下其內部的實現的某些關鍵機制,否則的話,就很可能就會犯下面這個的錯誤。
#include <map> #include <string> #include <iostream> using namespace std;class CKey { public:CKey(const int keyValue, const string keyName): m_KeyValue(keyValue), m_KeyName(keyName){}bool operator < (const CKey &key) const{return m_KeyValue < key.m_KeyValue;}bool operator == (const CKey &key) const{return m_KeyName == key.m_KeyName;}private:int m_KeyValue;string m_KeyName; };class CValue { };int main() {map<CKey, CValue> key2Value;CKey key(0, "Alpha");CValue value;key2Value.insert(make_pair(key, value));CKey objKey(1, "Alpha");auto it = key2Value.find(objKey); //順便隆重推薦下C++11中的新特性,超爽的auto!cout << (it == key2Value.end()); }上面的代碼輸出什么呢,答案是1,意味著objKey在key2Value中查找不到,雖然CKey重載的==運算符是以m_KeyName為判斷依據,而objKey和key擁有相同的m_keyName,但是map似乎根本不領情。
真相就是,對于map而言,它只關心<運算符,所以上面CKey中重載的==運算符對于map而言是沒有任何作用的。
接下來的問題就是,沒有==運算,map怎么知道自己找到了符合要求的那個元素呢?
其實,map雖然不知道等于的定義,但是它通過小于符號,知道了另外一種等價的定義,如果!(a < b) && !(b < a),那么a和b可以視為相等。
map的本質是一棵用key組建起來的紅黑樹(是一種對于每個樹節點,左邊元素全部小于父節點,右邊元素全部大于父節點的平衡二叉樹),find函數從map的根節點出發,如果根節點比要查找的F小,則移動到根節點的右子節點,否則移動到key節點的左子節點,再將移動后的節點視為根節點,重復上面的操作,直到遍歷到某個節點沒有需要的子節點為止。在遍歷的過程中,關鍵的一點在于更新最后一個不小于F的樹節點M(M初始為map的end())。最后比較F < M是否成立,如果成立,說明map中不存在要查找的元素F,否則,說明找到了需要查找的元素,就是記錄到的M,因為滿足了!(M < F) && !(F < M)。
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 10
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?/\
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?5 ? ? ?15
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? /\ ? ? ? ?/\
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 3 ? 6 ? 12 ?17
例如要從上面的樹中查找15這個值。初始M=end,首先10 < 15,遍歷到15;15 !< 15,更新M=15,遍歷到12;12 <15,尋找12的右子節點,為空,遍歷結束。記錄到的節點M=15,15 < M不成立,所以認為查找到了。
若要查找11這個值,同樣初始M=end,首先10 < 11,遍歷到15;15 !< 11,更新M=15,遍歷到12;12!<11,更新M=12,尋找12的左子節點,為空,遍歷結束。記錄到的節點是M=12,11 < M成立,所以認為查找失敗了。
具體情況推薦大家去看STL的源碼,上面都是根據VC++ STL源碼得到的。
?
轉載于:https://www.cnblogs.com/itZhy/archive/2012/10/03/2710866.html
總結
以上是生活随笔為你收集整理的仅靠“小于运算“生存的map的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Android 使用数据库 SQlite
- 下一篇: 什么是强类型