青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

step by step

 

數據結構-散列1

    最近在看Bartosz Milewski的C++ In Action Industrial-Strength Programming Techniques,這本書很不錯,它不是語言基礎教程,全書主要介紹了許多工業強度的編程技術,如清理,隱藏實現細節,資源管理,共享,資源管理,使用標準模板庫,重載運算符等技術。這是Bartosz Milewski的簡介:Bartosz Milewski,C++ In Action 的作者。是Reliable Software公司的總裁,Reliable Software公司是一家為程序員制造高質量開發工具的公司。在過去幾年間,Bartosz Milewski在多家知名雜志發表了大量技術文章。在微軟工程工作的8年期間,他擔任Windows2000中Content Index組件的開發主管,他曾經在波蘭的Wroclaw大學講授C++編程課程,而且他獲得了Wroclaw大學的理論物理學博士學位。 這是他為這本書管理的blog:http://www.relisoft.com/forums/index.php?s=ee4c0dc7cafef9f08c7c18a6e449b424&showforum=3,售后服務還不錯,呵呵,以我目前的水平看起來還挺累的,我想最好把C++ Primer和effective c++,more effective c++看完再看這本書會比較好,不過硬著頭皮看也有好處,就像有時候武俠小說里用非常規方法提高修為有時候也能起到意想不到的效果。言歸正傳,在這本書中多次用到哈希表,很多地方不明白,查了書整理一下。
   
    散列表(hash table)的實現常稱為散列(hashing),散列是一種用于以常數平均時間執行插入,刪除和查找的技術。但是,那些需要元素間任何排序信息的樹操作不會得到有效的支持。因此諸如findMin,findMax以及在線性時間內按順序打印整個表的操作都是散列所不支持的。
    我們把表的大小記作TableSize,我們把每個鍵映射到從0到TableSize-1這個范圍中的某個數,并且將其放到適當的單元中。這個映射就稱為散列函數(hash function),理想情況下它應該運算簡單并且應該保證任何兩個不同的鍵映射到不同的單元。不過,這是不可能的。因此我們尋找一個散列函數,該函數要在單元之間均勻分配鍵。這就是散列的基本思想,剩下的問題則是要選擇一個函數,決定當兩個鍵散列到同一個值的時候(稱為(collision))應該做什么以及如何確定散列表的大小。

1.散列函數
    如果輸入的鍵是整數,一般合理的方法就是直接返回"Key mod Tablesize",但Key具有某些不理想的性質,比如若表的大小是10而鍵的各位都是0。則此時上述標準的散列函數就不是一個好的選擇,好的辦法通常是保證表的大小是素數,當輸入的鍵是隨機整數時,散列函數不僅運算簡單而且鍵的分配也很均勻。
    通常,鍵是字符串;在這種情形下,散列函數需要仔細選擇。
    一種選擇方法是把字符串中字符的ASCII碼值加起來,下面的例程實現了這種策略。
   

1int hash( const string &key, int tableSize )
2{
3    int hashVal = 0;
4    forint i=0; i<key.length(); i++ )
5        hashVal += key[i];
6    return hashVal % tableSize;
7}

    上述散列函數實現起來簡單而且能夠很快地算出答案。不過如果表很大,則函數就不會很好地分配鍵。例如,設TableSize=10007(10007是素數),并設所有的鍵至多8個字符長,由于ASCII字符的值最多是127,因此散列函數只能在0-1016之間取值,顯然這不是一種均勻的分配。
    另一個散列函數如下表示,這個散列函數假設Key至少三個字符。值27表示英文字母表的字母個數外加一個空格,而729是27×27,該函數只考察前三個字符,但是如果它們是隨機的,而表的大小還是10007,那么我們就會得到一個合理的均衡分布。可是,英文不是隨機的。雖然3個字符(忽略空格)有26×26×26=17576種可能的組合,但查驗詞匯量足夠大的聯機詞典卻揭示出,3個字母的不同組合數實際上只有2851。即使這些組合沒有沖突,也不過只有表的28%被真正散列到。因此,雖然很容易計算,但是當散列表足夠大的時候這個函數還是不合適的。

1int hash( const string &key, int tableSize )
2{
3    return (key[0]+27*key[1]+729*key[2]) % tableSize
4}


    下面的例程列出了第3種嘗試。這個散列函數涉及鍵中的所有字符,并且一般可以分布得很好,程序根據Horner法則計算一個37的多項式函數。這個散列函數利用了允許溢出這個事實。這可能會引進負數,因此在末尾有附加的測試,這個散列函數就表的分布而言未必是最好的,但是確實具有極其簡單的優點而且速度也很快。如果鍵特別長,那么該散列函數計算起來將會花費過多的時間。在這種情況下通常做法是不使用所有的字符。此時鍵的長度和性質將影響選擇。例如,鍵可能是完整的街道地址,散列函數可以包括街道地址的幾個字符,或許也包括城市名和郵政編碼的幾個字符。有些程序設計人員通過只使用奇數位置上的字符來實現他們的散列函數,這里有這么一層想法:用計算散列函數節省下的時間來補償由此產生的對均勻分布的函數的輕微干擾。

 1int hash( const string &key, int tableSize )
 2{
 3    int hashVal = 0;
 4    for(int i=0;i<key.length();i++)
 5        hashVal = 37 * hashVal + key[i];
 6    hashVal %= tableSize;
 7    if( hashVal <0 )
 8        hashVal += tableSize;
 9    return hashVal;
10}

    剩下的主要編程細節是解決沖突。如果當一個元素在插入時與一個已經插入的元素散列到相同的值,那么就產生一個沖突,這個沖突需要消除。



2.分離鏈接法
    解決沖突的第一種方法通常稱為分離鏈接法(separate chaining),其做法是將散列到同一個值的所有元素保留到一個鏈表中,可以使用標準庫中表的實現方法。如果空間很緊,則更可取的方法是避免使用它們(因為這些表是雙向鏈表,浪費空間),為執行search,我們使用散列函數來確定究竟該遍歷那個鏈表,然后查找相應的表。為執行insert,我們檢查相應的表來確定是否該元素已經在表中了(如果要插入重復元,那么通常要留出一個額外的數據成員,當出現匹配事件時這個數據成員增1),如果這個元素是個新的元素,那么它將被插入到表的前端,這不僅因為方便,而且還因為最后插入的元素最有可能不久再次被訪問,實現分離鏈接法所需要的類架構在下面的例程中給出。散列表結構存儲一個鏈表數組,這個數組在構造函數中指定。

 1//分離鏈接散列表的類構架
 2template <typename HashedObj>
 3  class HashTable
 4 {
 5public:
 6    explicit HashTable( int size = 101 );
 7
 8    bool contains( const HashedObj &x ) const;
 9
10   void makeEmpty();
11   void insert( const HashedObj x);
12   void remove( const HashedObj x);
13
14 private:
15    vector<list<HashedObj> > theLists;// >>是c++的一個運算符,而且比>長,因此兩個>之間需要一個空格
16    int currentSize;
17    
18    void rehash()
19    int myhash( const HashedObj &x ) const;
20};
21
22int hash( const string &key );
23int hash( int key );
24
25    

    這里不使用那些將對象和類的大小作為參數的散列函數,而是使用那些僅以對象為參數的散列函數,并且返回int。散列表類有一個私有的成員函數myhash,這個函數將結果分配到一個合適的數組索引中。

 1int myhash( const HashedObj &x ) const
 2{
 3    int hashVal = hash(x);
 4    hashVal %=theLists.size();
 5    if( hashVal < 0)
 6        hashVal += theLists.size();
 7    return hashVal;
 8}

 9     
10

     下面的例程中列出了一個可以存儲在一般散列表中的Employee類,該類使用name成員作為鍵,Employee類通過提供相等性操作符和一個散列函數來實現HashedObj的需求。

 1class Employee
 2{
 3public:
 4    const string & getname() const
 5        return name; }
 6    bool operator==const Employee &rhs )  const
 7        return getName() == rhs.getName(); }
 8    bool operator!=const Employee & rhs }
 const
 9        return !(*this == rhs); }
10
11private:
12    string name;
13    double salary;
14    int seniority;
15};
16
17int hash( const Employ &item )
18{
19    return hash( item.getName() );
20}

    實現makeEmpty,contains和remove的程序代碼如下

 1void makeEmpty()
 2 {
 3    forint i=0; i<theLists.size();i++ )
 4        theLists[i].clear();
 5}

 6
 7bool contains( const HashedObj &x ) const
 8{
 9    const list<HashedObj> & whichList = theLists[myhash(x)];
10    return find( whichList.begin(),whichList.end(),x) !=whichList.end();
11}

12
13bool remove( const HashedObj &x )
14{
15    list<HashedObj> &whichList = theLists[myhash(x)];
16    list<HashedObj>::iterator itr = find(whichList.begin(),whichList.end(),x);
17    if( itr == whichList.end() )
18        return false;
19    whichList.erase( itr );
20    --currentSize;
21    return true;
22}

    下一個操作是插入例程。如果要插入的項已經存在,那么什么都不做;否則將其放至表的前端。該元素可以放在表的任何地方;此處使用push_back是最方便的。whichList是一個引用變量

 1bool insert ( const HashedObj &x )
 2{
 3    list<HashedObj> & whichList = theLists[ myhash(x) ];
 4    if( find( whichList.begin(),whichList.end(),x )!=whichList.end() )
 5        return false;
 6    whichList.push_back(x);
 7    
 8    if(++currentSize > theLists.size() )
 9        rehash();
10
11    return true;
12}



 

posted on 2009-11-25 22:22 小羅羅 閱讀(842) 評論(0)  編輯 收藏 引用


只有注冊用戶登錄后才能發表評論。
網站導航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


導航

統計

常用鏈接

留言簿

隨筆檔案

搜索

最新評論

閱讀排行榜

評論排行榜

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            91久久午夜| 日韩一区二区电影网| 亚洲国产欧美精品| 国产婷婷色一区二区三区| 欧美午夜精品一区| 欧美高清视频在线播放| 久热精品视频在线| 久久久久久97三级| 久热精品在线| 欧美剧在线免费观看网站| 欧美黑人多人双交| 欧美日韩国产精品| 欧美日韩一区二| 国产精品久久久久毛片大屁完整版 | 免费观看国产成人| 亚洲综合好骚| 欧美在线看片| 激情欧美日韩一区| 亚洲欧洲一区二区三区在线观看| 久久综合网络一区二区| 免费成人毛片| 亚洲精品美女91| 亚洲一区三区电影在线观看| 亚洲欧美日韩国产一区| 午夜国产欧美理论在线播放| 午夜精品久久久久久久久久久久 | 欧美精品福利在线| 欧美日韩激情小视频| 国产欧美日韩不卡免费| 亚洲日本乱码在线观看| 亚洲在线成人| 亚洲福利视频一区| 亚洲一区二区三区免费在线观看 | 怡红院精品视频在线观看极品| 亚洲激情在线播放| 欧美在线观看一区二区| 亚洲电影免费| 午夜亚洲影视| 欧美视频国产精品| 亚洲电影视频在线| 亚洲一区二区免费视频| 欧美大片免费久久精品三p| 一区二区不卡在线视频 午夜欧美不卡在 | 亚洲一区二区三区高清| 亚洲欧美日本日韩| 欧美在线综合| 亚洲三级网站| 午夜精品国产更新| 美女精品自拍一二三四| 一片黄亚洲嫩模| 久久精品国产2020观看福利| 免费视频一区| 欧美日韩久久久久久| 国内精品久久久久伊人av| 91久久久一线二线三线品牌| 香港久久久电影| 欧美a级一区| 亚洲国产精品高清久久久| 亚洲欧美日韩系列| 欧美激情视频在线播放| 国产精品99久久不卡二区| 欧美午夜宅男影院| 在线不卡欧美| 亚洲综合日韩在线| 亚洲国产精品成人精品| 欧美亚洲系列| 国产精品极品美女粉嫩高清在线| 黄色小说综合网站| 欧美制服丝袜| 在线一区免费观看| 欧美激情视频一区二区三区在线播放| 国产亚洲精品综合一区91| 艳妇臀荡乳欲伦亚洲一区| 亚洲国产福利在线| 欧美亚洲日本网站| 亚洲美女av在线播放| 香蕉免费一区二区三区在线观看| 欧美jizz19性欧美| 狠狠色丁香久久婷婷综合丁香 | 欧美乱大交xxxxx| 欧美高清在线观看| 好看的日韩av电影| 久久不射中文字幕| 亚洲永久免费av| 国产精品永久| 欧美在线观看www| 蜜臀av在线播放一区二区三区 | 免费短视频成人日韩| 国产一区二区精品久久| 欧美一级在线亚洲天堂| 日韩亚洲欧美一区| 欧美日韩第一页| 夜久久久久久| 在线视频欧美精品| 国产精品另类一区| 欧美自拍丝袜亚洲| 久久精品国产第一区二区三区| 国产精品亚洲美女av网站| 曰本成人黄色| 男男成人高潮片免费网站| 美女在线一区二区| 亚洲精选中文字幕| 日韩一二在线观看| 国产精品自拍三区| 久久亚洲精品欧美| 久久午夜电影| 国内精品视频666| 一本高清dvd不卡在线观看| 亚洲人成网站在线播| 欧美日韩在线影院| 久久精品72免费观看| 久久久久久97三级| 夜夜嗨一区二区三区| 亚洲欧美大片| 亚洲精品久久久一区二区三区| 99re热精品| 亚洲一区二区精品在线| 国产精品久久国产精品99gif| 午夜一区二区三区在线观看| 欧美一区亚洲一区| 久久精品噜噜噜成人av农村| 亚洲一区二区高清视频| 亚洲与欧洲av电影| 国产欧美日韩综合一区在线观看 | 久久精品国产清自在天天线| 狠狠久久亚洲欧美专区| 亚洲成色777777女色窝| 欧美精品一区二区三区很污很色的 | 一区二区三区视频在线| 国产精品福利网站| 久久精品视频在线看| 久久亚洲影院| 午夜精品久久久久久久白皮肤| 久久国产视频网| 亚洲影院在线| 欧美大片免费看| 久久久欧美精品sm网站| 欧美三日本三级三级在线播放| 久久另类ts人妖一区二区| 国产视频一区在线| 久久福利毛片| 久久亚洲图片| 香港久久久电影| 欧美日韩精品在线| 欧美激情第一页xxx| 国产亚洲激情| 亚洲小说欧美另类婷婷| 99综合视频| 美女久久网站| 男人的天堂亚洲在线| 国产日韩欧美综合精品| 亚洲网站视频福利| 狠狠88综合久久久久综合网| 中文一区二区| 国产精品99久久久久久久vr| 老司机午夜精品视频在线观看| 欧美主播一区二区三区| 欧美日韩另类一区| 亚洲青色在线| 亚洲精品视频中文字幕| 免费高清在线一区| 久久亚洲美女| 日韩视频永久免费| 在线精品视频一区二区| 亚洲欧美一区二区三区久久 | 亚洲区中文字幕| 精品99视频| 久久久精品动漫| 麻豆91精品| 在线观看日产精品| 久久免费高清| 欧美激情1区2区3区| 在线成人www免费观看视频| 欧美在线视频一区| 美女脱光内衣内裤视频久久影院| 国内自拍视频一区二区三区| 久久精品亚洲乱码伦伦中文| 欧美成人在线影院| 日韩亚洲国产精品| 欧美性大战xxxxx久久久| 亚洲天堂免费在线观看视频| 午夜精品偷拍| 国语自产偷拍精品视频偷| 老司机aⅴ在线精品导航| 久久综合图片| 国产婷婷97碰碰久久人人蜜臀| 欧美一级午夜免费电影| 久久在线免费| 一本色道久久综合| 国产精品一区二区久久| 狠狠操狠狠色综合网| 亚洲国产欧美一区二区三区久久| 久久中文字幕一区二区三区| 亚洲精品免费在线| 小黄鸭精品aⅴ导航网站入口 | 国产亚洲a∨片在线观看| 老牛国产精品一区的观看方式| 久久久中精品2020中文| 这里只有精品视频| 国产精品jvid在线观看蜜臀|