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

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 小羅羅 閱讀(845) 評論(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>
            久热精品视频在线观看一区| 欧美日韩国产三区| 亚洲尤物视频网| 久久综合久久久久88| 性欧美xxxx视频在线观看| 欧美风情在线| 欧美成年人网站| 国产一区二区三区四区五区美女| 一区二区激情视频| 亚洲伦理在线免费看| 久久久女女女女999久久| 欧美一级淫片播放口| 欧美日韩视频在线| 欧美激情亚洲精品| 亚洲国产成人在线| 久久久人成影片一区二区三区观看 | 亚洲人成亚洲人成在线观看图片 | 狠狠色综合一区二区| 亚洲永久精品大片| 亚洲自拍偷拍麻豆| 欧美日韩性生活视频| 亚洲区国产区| 日韩一区二区免费高清| 欧美顶级大胆免费视频| 欧美+亚洲+精品+三区| 伊人久久婷婷色综合98网| 久久精品国产一区二区电影| 久久久国产一区二区三区| 国产一区二区观看| 久久久www成人免费无遮挡大片| 久久久久成人精品免费播放动漫| 国产欧美一区在线| 欧美在线观看视频一区二区三区| 久久久噜噜噜久噜久久| 伊人男人综合视频网| 久久综合九色欧美综合狠狠| 欧美激情视频一区二区三区不卡| 亚洲高清资源| 欧美日韩裸体免费视频| 亚洲桃花岛网站| 午夜精彩国产免费不卡不顿大片| 国产欧美日韩不卡| 久久久国产成人精品| 亚洲第一综合天堂另类专| 99re视频这里只有精品| 国产精品高清免费在线观看| 亚洲欧美日韩中文播放| 每日更新成人在线视频| 亚洲欧洲日本国产| 欧美日韩国产综合一区二区| 亚洲自拍高清| 欧美chengren| 亚洲免费视频观看| 激情视频一区| 欧美日韩亚洲免费| 欧美在线免费看| 亚洲人体影院| 久久久久久久久久久久久久一区| 亚洲大黄网站| 欧美午夜在线观看| 久久综合电影| 亚洲字幕在线观看| 亚洲国产高清高潮精品美女| 先锋影音久久久| 亚洲欧洲一区| 国产日韩精品久久久| 欧美国产日本韩| 欧美在线播放视频| 亚洲美女毛片| 欧美国产第二页| 欧美一区二区视频在线观看| 亚洲精品美女在线观看播放| 国产麻豆精品久久一二三| 欧美成人综合网站| 久久精品视频99| 亚洲调教视频在线观看| 亚洲国产第一| 麻豆免费精品视频| 久久xxxx| 亚洲欧美日韩国产成人| 亚洲乱码日产精品bd| 国内精品美女av在线播放| 欧美天堂亚洲电影院在线观看| 另类欧美日韩国产在线| 欧美一区二区在线视频| 亚洲美女视频在线免费观看| 欧美福利电影在线观看| 久久久久国产精品一区| 亚洲欧美韩国| 在线亚洲伦理| 亚洲精品久久久久久久久久久| 国产亚洲欧洲一区高清在线观看| 欧美性一区二区| 欧美日韩成人在线| 欧美 日韩 国产在线| 久久成人精品视频| 欧美一级视频一区二区| 亚洲欧美日韩国产综合在线| 在线亚洲精品| 国产精品99久久久久久人| 亚洲精品色婷婷福利天堂| 亚洲国产视频a| 欧美激情在线有限公司| 欧美gay视频激情| 欧美高潮视频| 亚洲电影免费观看高清| 猛干欧美女孩| 欧美激情影院| 亚洲国产精品久久久| 亚洲国产婷婷香蕉久久久久久| 欧美黑人在线播放| 欧美高潮视频| 亚洲国产天堂久久国产91| 亚洲欧洲另类| 日韩亚洲欧美一区| 99国产精品一区| 一区二区三区高清视频在线观看| 99国产麻豆精品| 亚洲永久在线| 久久激情一区| 欧美成人免费va影院高清| 欧美精品在线网站| 欧美日韩精品一区二区三区四区| 欧美性猛交xxxx免费看久久久| 国产精品高精视频免费| 国产亚洲激情视频在线| 在线国产日韩| 日韩视频国产视频| 午夜精品久久久久久99热软件| 欧美亚洲在线视频| 浪潮色综合久久天堂| 91久久精品国产91性色tv| 99在线观看免费视频精品观看| 亚洲综合色网站| 久久手机免费观看| 欧美日韩精品一区二区天天拍小说 | 国产精品99久久久久久久久久久久 | 亚洲激情不卡| 亚洲天堂成人| 久久视频在线视频| 国产精品h在线观看| 国产色综合久久| 亚洲人永久免费| 午夜免费在线观看精品视频| 久久综合一区二区| 99re亚洲国产精品| 久久成人免费| 欧美午夜不卡| 亚洲国内精品| 香蕉免费一区二区三区在线观看 | 欧美一区二区私人影院日本| 你懂的亚洲视频| 亚洲私人影院| 欧美成年人视频| 国产日韩精品在线观看| 99xxxx成人网| 美国成人毛片| 午夜日本精品| 欧美日韩国产综合一区二区| 精品不卡视频| 欧美亚洲一区二区三区| 亚洲高清视频一区| 欧美一区在线直播| 欧美午夜在线一二页| 亚洲黄页一区| 蜜臀av性久久久久蜜臀aⅴ四虎| 在线视频精品一| 欧美美女bb生活片| 亚洲国产精品一区二区三区| 久久精品日产第一区二区| 一区二区久久| 欧美精品一区二区高清在线观看| 国产字幕视频一区二区| 亚洲午夜久久久久久久久电影院 | 国产专区欧美专区| 亚洲一级电影| 亚洲国产mv| 欧美成人综合| 亚洲国产婷婷| 欧美二区在线播放| 久久精品一区二区三区中文字幕| 国产精品日本| 午夜精品视频一区| 夜夜嗨av一区二区三区中文字幕 | 一本色道久久综合亚洲精品不卡 | 久久精品国产亚洲aⅴ| 国产欧美在线观看| 午夜一区二区三视频在线观看| 亚洲精品久久久久久久久| 欧美福利一区二区| 亚洲黄色毛片| 亚洲高清视频一区二区| 媚黑女一区二区| 亚洲精品在线二区| 亚洲电影免费在线 | 亚洲精品视频在线观看网站| 欧美国产一区视频在线观看| 男人的天堂亚洲在线| 亚洲国产精品悠悠久久琪琪| 欧美v国产在线一区二区三区|