• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            兔子的技術(shù)博客

            兔子

               :: 首頁 :: 聯(lián)系 :: 聚合  :: 管理
              202 Posts :: 0 Stories :: 43 Comments :: 0 Trackbacks

            留言簿(10)

            最新評論

            閱讀排行榜

            評論排行榜

            Hash

            我曾在很多C++書籍中看到作者們抱怨標(biāo)準(zhǔn)庫中沒有實(shí)現(xiàn)hash_sethase_map,并非常自信地聲稱在下一個(gè)標(biāo)準(zhǔn)庫中一定會(huì)增加這兩個(gè)。我搜索的幫助文檔后,很遺憾地沒有發(fā)現(xiàn)相關(guān)庫。難道C++的狂熱愛好者把這么重要的庫給忘記了嗎?Boost.Functional/hash庫引進(jìn)了我的注意,遵循它的指引,我一步一步發(fā)發(fā)現(xiàn)的散列表的蹤跡。

            hash        <boost/functional/hash.hpp>

            觀察頭文件的寫法,就知道hashfunctional庫中的一員,更進(jìn)一步,如果你用過STL中的<functional>,那么多半你也猜到,hash是一個(gè)函數(shù)。不太完全正確,實(shí)事上它是一個(gè)函數(shù)對象。boost中實(shí)現(xiàn)的散列表,使用的散列函數(shù)就是它(至于boost中有那些散列函數(shù),以后再列舉)。

            如果直接使用hash,先創(chuàng)建一個(gè)實(shí)例并像函數(shù)一樣調(diào)用它:

                   hash<string> string_hash;

                   size_t h = string_hash(“Love”);

            它支持的類型有

            integers

            floats

            pointers

            strings

            擴(kuò)展類型有

            arrays

            std::pair

            標(biāo)準(zhǔn)容器

            定制的類型擴(kuò)展

            如何定制類型

            要編寫一個(gè)hash可用的類型,兩個(gè)必須實(shí)現(xiàn)的功能是operator==  hash_value,參考下面的實(shí)現(xiàn):

            namespace library {

                   struct book {

                          int id;

                          std::string titile;

                   };

                   std::size_t hash_value(const book& b) {

                          boost::hash<int> hasher;

                          return hasher(b.id); // 可以自己寫哈希函數(shù)

                   }

                   bool operator== (const book& a, const book& b) const {

                          return a.id == b.id;

                   }

            }; // namespace library

            結(jié)合散列值

            縱觀上面的hash使用方法,只能對一個(gè)參數(shù)可hash值。庫也提供了多個(gè)參數(shù),示例:

            class point {

                   int x, y;

            public:

                   … …

                   bool operator==(const point& other) const {      

                          return x == other.x && y == other.y;

                   }

                   friend std::size_t hash_value(const point& p) {

                          std::size_t seed = 0;

                          boost::hash_combin(seed, p.x);     // combin 的順序不同,得出的結(jié)果也不同

                          boost::hash_combin(seed, p.y);

                          return seed;

            };

            Unordered      <boost/unordered_set.hpp> ,<boost/unordered_map.hpp>

            這個(gè)庫實(shí)現(xiàn)了無序關(guān)聯(lián)容器。從某種意義上說,它就是我們需要的散列表。

            與有序關(guān)聯(lián)容器不同的是,它不需要比較,而是需要hash值。我下面列出它的聲明,以求不要理解錯(cuò)了。

            namespace boost {

                   template <

                          class Key,

                          class Hash = boost::hash<Key>,

                          class Pred = std::equal_to<Key>,

                          class Alloc = std::alloctor<Key> >

                   class unordered_set;

            }

            如果class不是標(biāo)準(zhǔn)庫里的類型,那么hashequal_to的非常關(guān)鍵了。

            使用

            unordered_setunordered_mapsetmap在使用上基本一致。請參考它們的寫法。

            更深層次的探索

            散列表一個(gè)不可避免的問題即是“沖突”,解決沖突的方法有很多,有分離鏈表法、線性探測等。據(jù)我所知道,分離鏈表法是在各種庫最常用的方法。unordered的實(shí)現(xiàn)用到了桶(bucket),這屬于分離鏈表的變體。每桶對應(yīng)的是索引,桶里可以有很多元素,它們都是“沖突”的。

            線性探測中,一個(gè)非常重要的數(shù)據(jù)就是:裝填因子λ,它是散列表中的元素個(gè)數(shù)與散列表大小的比值。對于探測散列表,λ≈0.5;對于分離鏈表,λ≈1。在手冊中,unordered中負(fù)載因子(load factor)的解釋是“the average number of elements per bucket”,平均每個(gè)桶中元素的個(gè)數(shù),在數(shù)學(xué)上,此處的負(fù)載因子與前面的裝填因子λ等價(jià)。

            以下幾個(gè)函數(shù)用于控制桶的大小

            X( size_type n)                                  構(gòu)造一個(gè)新容器,帶有n個(gè)桶

            X( InputIterator i, InputIterator j, size_type n)            構(gòu)造有n個(gè)的容器,插入?yún)^(qū)間[i, j)

            float load_factor( ) const                            每個(gè)桶中的平均數(shù)量

            float max_load_factor( ) const             當(dāng)前最大的負(fù)載因子

            float max_load_factor( float z)             修改最大負(fù)載因子,z做為參數(shù)

            void rehash( size_type n)                     修改桶使至少為n個(gè),且負(fù)載因子小于最大負(fù)載因子

            除了 rehash 以外,其它成員函數(shù)如何影響桶的數(shù)量并沒有規(guī)定,insert 操作僅當(dāng)插入導(dǎo)致負(fù)載因子大于或等于最大負(fù)載因子時(shí)允許使得迭代器失效。對于多數(shù)實(shí)現(xiàn)來說,這意味著只有當(dāng)此事發(fā)生時(shí),插入操作才會(huì)改變桶的數(shù)量。因此,迭代器只會(huì)在調(diào)用 insert  rehash 時(shí)才可能失效,而指向容器中的元素的指針和引用則永不失效。


            轉(zhuǎn)自:http://hi.baidu.com/ani_di/blog/item/41406ce6df3c1f24b83820c1.html

            posted on 2010-06-05 17:23 會(huì)飛的兔子 閱讀(7881) 評論(0)  編輯 收藏 引用 所屬分類: C++庫,組件
            久久国产色AV免费观看| 少妇高潮惨叫久久久久久| 一本久久久久久久| 国产99久久久久久免费看| 久久国产精品免费一区| 伊人久久五月天| 2021少妇久久久久久久久久| 91亚洲国产成人久久精品网址| 久久夜色撩人精品国产| 久久久久亚洲AV无码专区首JN| 久久精品国产第一区二区三区| 国产午夜精品理论片久久| 亚洲欧美伊人久久综合一区二区| 99久久婷婷国产综合亚洲| 久久久久婷婷| 久久九九亚洲精品| 亚洲国产精品久久久天堂| 久久婷婷五月综合97色直播| 久久久免费精品re6| 热久久视久久精品18| 91久久香蕉国产熟女线看| 午夜精品久久久久久毛片| 一本久久综合亚洲鲁鲁五月天| 91久久精一区二区三区大全| 一本久久知道综合久久| 亚洲另类欧美综合久久图片区| 99久久国产免费福利| 久久99精品久久久久久hb无码| 九九精品久久久久久噜噜| 国产ww久久久久久久久久| 久久精品国产亚洲av水果派| 狠狠色婷婷久久综合频道日韩| 看全色黄大色大片免费久久久| 国产精品伦理久久久久久| 热久久国产精品| 中文字幕久久欲求不满| 四虎国产永久免费久久| 久久精品九九亚洲精品天堂| 久久精品国产99久久无毒不卡 | 久久久久人妻一区二区三区vr| 中文成人久久久久影院免费观看|