• <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++庫,組件
            久久亚洲高清综合| 日韩电影久久久被窝网| 99久久精品毛片免费播放| 99久久99久久久精品齐齐| 国产成人久久777777| 久久久高清免费视频| 精品国产乱码久久久久久郑州公司| 国产精品久久久久影视不卡| 久久亚洲欧洲国产综合| 精品久久久久中文字幕日本| 91精品国产综合久久四虎久久无码一级 | 看全色黄大色大片免费久久久| 囯产极品美女高潮无套久久久| 久久91精品久久91综合| 久久天天躁夜夜躁狠狠| 久久男人中文字幕资源站| 国产成人久久激情91| 精品国产乱码久久久久久人妻 | 国产精品成人99久久久久91gav| 亚洲成色WWW久久网站| 伊人 久久 精品| 欧美久久一区二区三区| 久久99国产一区二区三区| 久久99精品国产| 99久久国产综合精品麻豆| 午夜不卡久久精品无码免费| 国产精品乱码久久久久久软件| 天天综合久久久网| 久久国产精品-久久精品| 狠狠色噜噜狠狠狠狠狠色综合久久| 国产A级毛片久久久精品毛片| 久久久这里有精品| 亚洲综合久久久| 精品伊人久久大线蕉色首页| 97精品伊人久久大香线蕉| 久久午夜夜伦鲁鲁片免费无码影视| 久久Av无码精品人妻系列| 久久精品国产福利国产秒| 伊人久久五月天| 18禁黄久久久AAA片| 久久久久免费精品国产|