• <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>

            step by step

             

            散列3

              散列這是最后一章了,快畢業(yè)了,這幾天趕快把論文寫完,到回家還不到兩個(gè)月,答應(yīng)張老師再去實(shí)驗(yàn)室把做的東西總結(jié)一下,其實(shí)打算在實(shí)驗(yàn)室再呆兩個(gè)月,臘月底再回,想寫的東西嘛,我想研究一下opencv的內(nèi)存管理機(jī)制,結(jié)合我買的那本Applied C++,順便推銷一下這本書,這本書很薄,兩百多頁(yè),介紹如何應(yīng)用c++來(lái)解決開發(fā)商業(yè)軟件時(shí)所固有的問(wèn)題,最難能可貴的是,從頭至尾提供了一個(gè)圖像處理框架,對(duì)于想在數(shù)字圖像處理,機(jī)器視覺方向深入探究(不是具體算法,而是整個(gè)軟件架構(gòu))有挺大的啟發(fā)意義的(雖然網(wǎng)上評(píng)價(jià)不是太好,可能比較牛的人看不上吧,也有可能這本書比較偏重于數(shù)字圖像領(lǐng)域),還想學(xué)的東西呢,年前和年后幾個(gè)月的時(shí)間Bjarne Stroustrup的那本c++,Mark Allen Weiss的那本數(shù)據(jù)結(jié)構(gòu),Jon Kleinberg 的那本算法設(shè)計(jì),后兩本書是俺在圖像室的圖書角找到的,非常的不錯(cuò)哦,可惜畢業(yè)前就要還,正好督促我趕緊看,在聯(lián)合書城看到Richard Johnsonbaugh的Discrete Mathematics,竟然是第七版了,只能怪我資質(zhì)太差看不懂knuth的那三本圣經(jīng),只好咬著牙買下來(lái)先琢磨琢磨了算是打基礎(chǔ)了,公司有項(xiàng)目做嵌入式平臺(tái)上的編譯器,要是有時(shí)間的話看看嵌入式操作系統(tǒng)和編譯原理吧,很想寫個(gè)編譯器,這么多好書要看,有時(shí)候真不想回家過(guò)年了,嘿嘿,說(shuō)著玩的,到時(shí)候家里肯定殺豬了,不回去真是太可惜了。

            1.再散列
               其實(shí)就是前兩篇中有提到的rehash了,對(duì)于使用平方探測(cè)的開放定制散列法,如果表的元素填得太滿,那么操作的運(yùn)行時(shí)間將開始消耗過(guò)長(zhǎng),且插入操作可能失敗。這可能發(fā)生在有太多刪除和插入混合的場(chǎng)合。此時(shí),一個(gè)解決方法是建立另外一個(gè)大約兩倍大的表(而且使用一個(gè)相關(guān)的新散列函數(shù)),掃描整個(gè)原始散列表,計(jì)算每個(gè)(未刪除的)元素的新散列值并將其插入到新表中。整個(gè)操作成為再散列(rehashing)。這顯然是一種非常昂貴的操作;其運(yùn)行時(shí)間為O(N),因?yàn)橛蠳個(gè)元素要再散列而且表的大小約為2N,不過(guò),因?yàn)椴皇墙?jīng)常發(fā)生,所以實(shí)際效果并沒有這么差。特別是,在最后的再散列之前已經(jīng)存在N/2次插入,因此添加到每個(gè)插入上的花費(fèi)基本是一個(gè)常數(shù)開銷。如果這種數(shù)據(jù)結(jié)構(gòu)是程序的一部分,那么其影響是不明顯的。另一方面,如果再散列作為交互系統(tǒng)一部分運(yùn)行,那么其插入引起再散列的用戶將會(huì)感到速度減慢。
                再散列可以用平方預(yù)測(cè)以多種方法實(shí)現(xiàn)。一種做法是只要表滿一半就再散列。另一種極端的方法是只有當(dāng)插入失敗時(shí)才再散列。第三種方法即途中(middle-of-the-road)策略:當(dāng)表到達(dá)某一個(gè)裝填因子時(shí)進(jìn)行再散列。由于隨著裝填因子的增加,表的性能的確在下降,因此,以好的截至點(diǎn)實(shí)現(xiàn)的第三種策略,可能是最好的策略。
             1//對(duì)探測(cè)散列表和分離鏈接散列表的再散列
             2void rehash()
             3{
             4    vector<HashEntry> oldArray = array;
             5    array.resize( nextPrime( 2* oldArray.size() ) );
             6    forint j = 0; j<array.size(); j++ )
             7        array[j].info = EMPTY;
             8    currentSize = 0;
             9    forint i = 0; i<oldArray.size(); i++ )
            10        if( oldArray[i].info == ACTIVE )
            11            insert( oldArray[i].element );
            12}

            13
            14void rehash()
            15{
            16    vector<list<HashedObj> > oldLists = theLists;
            17    theLists.resize( nextPrime( 2* theLists.size() ) );
            18    forint j = 0; j<theLists.size(); j++ )
            19        theLists[j].clear();
            20    currentSize = 0;
            21    forint i = 0; i<oldLists.size(); i++ )
            22    {
            23        list<HashedObj>::iterator itr = OldLists[i].begin();
            24        while ( itr != oldLists[i].end() )
            25            insert( *itr++ );
            26    }

            27}


            2.標(biāo)準(zhǔn)庫(kù)中的散列表
                標(biāo)準(zhǔn)庫(kù)中不包括set和map的散列表實(shí)現(xiàn)。但是,許多的編譯器提供具有與set和map類相同的成員函數(shù)的hash_set和hash_map.
                要使用hash_set和hash_map,就必須有相應(yīng)的包含指令,而且,可能也需要相應(yīng)的命名空間。這兩者都是和編譯器相關(guān)的。接下來(lái)還必須提供相應(yīng)的類型參數(shù)來(lái)說(shuō)明
            hash_set和hash_map。對(duì)于hash_map,這些類型參數(shù)包括鍵的類型,值的類型,散列函數(shù)(返回?zé)o符號(hào)整數(shù))和一個(gè)相等性操作符。遺憾的是,至于鍵和值的類型參數(shù)如何
            表示還是編譯器相關(guān)的。
                下一次c++的較大的修訂將不可避免地包括這些hash_set和hash_map中的一個(gè)。

            3.可擴(kuò)散列
                最后討論數(shù)據(jù)量太大以至于裝不進(jìn)主存的情況,此時(shí)主要考慮的是檢索數(shù)據(jù)所需的磁盤存取次數(shù)。假設(shè)在任意時(shí)刻都有N個(gè)記錄要存儲(chǔ),N的值隨時(shí)間而變化。此外,最多可把M個(gè)記錄放入一個(gè)磁盤區(qū)塊,設(shè)M=4,如果使用探測(cè)散列或分離鏈接散列,那么主要的問(wèn)題在于,即使是理想分布的散列表,在一次查找操作中,沖突也可能引起對(duì)多個(gè)區(qū)塊的訪問(wèn)。不僅如此,當(dāng)表變得過(guò)慢的時(shí)候,必須執(zhí)行代價(jià)巨大的再散列這一步,它需要O(N)的磁盤訪問(wèn)。
                一種聰明的選擇成為可擴(kuò)散列(extendible hashing),它允許用兩次磁盤訪問(wèn)執(zhí)行一次查找。插入操作也需要很少的磁盤訪問(wèn).
               Extendible hashing from Wikipedia
               Extendible hashing
            is a type of hash system which treats a hash as a bit string, and uses a trie for bucket lookup. Because of the hierarchal nature of the system, re-hashing is an incremental operation (done one bucket at a time, as needed). This means that time-sensitive applications are less affected by table growth than by standard full-table rehashes.

               

            This is a more simplistic example from Fagin et al. (1979).

            Assume that the hash function h(k) returns a binary number. The first i bits of each string will be used as indices to figure out where they will go in the "directory" (hash table). Additionally, i is the smallest number such that the first i bits of all keys are different.

            Keys to be used:

            h(k1) = 100100
            h(k2) = 010110
            h(k3) = 110110

            Let's assume that for this particular example, the bucket size is 1. The first two keys to be inserted, k1 and k2, can be distinguished by the most significant bit, and would be inserted into the table as follows:

             directory
            ---------
            |    0    |-----------> Bucket A (contains k2)
            |---------|
            |    1    |-----------> Bucket B (contains k1)
            ---------
            

            Now, if k3 were to be hashed to the table, it wouldn't be enough to distinguish all three keys by one bit (because k3 and k1 have 1 as their leftmost bit. Also, because the bucket size is one, the table would overflow. Because comparing the first two most significant bits would give each key a unique location, the directory size is doubled as follows:

              directory
            ----------
            |    00    |-----\
            |----------|      ----------> Bucket A (contains k2)
            |    01    |-----/
            |----------|
            |    10    |-----------> Bucket B (contains k1)
            |----------|
            |    11    |-----------> Bucket C (contains k3)
            ----------
            

            And so now k1 and k3 have a unique location, being distinguished by the first two leftmost bits. Because k2 is in the top half of the table, both 00 and 01 point to it because there is no other key to compare to that begins with a 0.

            4.小結(jié)
                散列表可以用來(lái)以常數(shù)平均時(shí)間實(shí)現(xiàn)insert和contains操作。當(dāng)使用散列表時(shí),注意諸如裝填因子這樣的細(xì)節(jié)是特別重要的,否則時(shí)間界將不再有效。當(dāng)鍵不是短字符串或整數(shù)時(shí),仔細(xì)選擇散列函數(shù)也是很重要的。
                對(duì)于分離鏈接散列法,雖然裝彈因子不大時(shí)性能并不明顯降低,但裝填因子還是應(yīng)該接近于1,對(duì)于探測(cè)散列,除非完全不可避免,否則裝填因子不應(yīng)該超過(guò)0.5,如果使用線性探測(cè),那么性能隨著裝填因子接近于1而急速下降。再散列運(yùn)算可以通過(guò)使表增長(zhǎng)(或收縮)來(lái)實(shí)現(xiàn),這樣可以保持合理的裝填因子。對(duì)于空間緊缺并且不可能聲明巨大散列表的情況,這是很重要的。
                二叉查找樹也可以用來(lái)實(shí)現(xiàn)insert和contains操作。雖然平均時(shí)間界為O(logN),但是二叉查找樹也支持那些需要排序的例程,從而功能更強(qiáng)大,使用散列表不可能找出最小元素。除非準(zhǔn)確知道一個(gè)字符串,否則散列表也不可能有效地查找它。二叉查找樹可以迅速找到一定范圍內(nèi)的所有項(xiàng),散列表卻做不到。不僅如此,因?yàn)椴檎覙洳恍枰朔ê统ǎ琌(logN)這個(gè)時(shí)間界也不必比O(1)大那么多。
                另一方面,散列的最壞情形一般來(lái)自于實(shí)現(xiàn)錯(cuò)誤,而有序的輸入?yún)s可能使二叉樹運(yùn)行得很差。平衡查找樹實(shí)現(xiàn)的代價(jià)相當(dāng)高。因此,如果不需要排序的信息或者不確定輸入是否已經(jīng)排序,那么就應(yīng)該選擇散列這種數(shù)據(jù)結(jié)構(gòu)。
                散列的應(yīng)用很廣。編譯器使用散列表跟蹤源代碼中聲明的變量,這種數(shù)據(jù)結(jié)構(gòu)叫做符號(hào)表(symbol table)。散列表時(shí)這種問(wèn)題的理想選擇。標(biāo)識(shí)符一般都不長(zhǎng),因此散列函數(shù)能夠迅速完成運(yùn)算。此外,按字母順序排序變量通常也是不必要的。
                散列表適用于任何其節(jié)點(diǎn)有實(shí)名而不是數(shù)字名的圖論問(wèn)題。這里,當(dāng)輸入被讀入的時(shí)候,定點(diǎn)則按照它們出現(xiàn)的順序從1開始指定為一些整數(shù)。再有,輸入很可能有一組按字母順序排列的項(xiàng)。例如,頂點(diǎn)可以是計(jì)算機(jī)。此時(shí),如果一個(gè)特定的計(jì)算中心把它的計(jì)算機(jī)列表成ibm1,ibm2,ibm3...那么,若使用查找樹則在效率方面很可能會(huì)有戲劇性的結(jié)果。
               散列表的第三種常見的用途實(shí)在為游戲編制的程序中。當(dāng)程序搜索游戲的不同的運(yùn)動(dòng)路徑時(shí),它通過(guò)計(jì)算基于位置的散列函數(shù)而跟蹤一些已知的位置(并把對(duì)于該位置的移動(dòng)存儲(chǔ)起來(lái))。如果同樣的位置再次出現(xiàn),程序通常通過(guò)簡(jiǎn)單的移動(dòng)變換來(lái)避免昂貴的重復(fù)計(jì)算。游戲程序的這種一般特點(diǎn)叫做置換表(transposition table).
               散列的另一個(gè)用途是在線拼寫檢查程序。如果拼寫檢查程序的主要功能是檢查拼寫錯(cuò)誤(而非糾正錯(cuò)誤),那么可以預(yù)先將整個(gè)詞典進(jìn)行散列,這樣就可以在常數(shù)時(shí)間內(nèi)檢查單詞拼寫。散列表很適合這項(xiàng)工作,因?yàn)橐宰帜疙樞蚺帕袉卧~并不重要,而以它們?cè)谖募谐霈F(xiàn)的順序顯示錯(cuò)誤拼寫當(dāng)然也是可以接受的。

            posted on 2009-11-27 17:14 小羅羅 閱讀(952) 評(píng)論(7)  編輯 收藏 引用

            評(píng)論

            # re: 散列3 2009-11-27 18:34 OwnWaterloo

            研究opencv的內(nèi)存管理? 如果是為了使用opencv,可以去研究。

            如果是為了研究?jī)?nèi)存管理…… opencv的內(nèi)存管理其實(shí)很磋……
            當(dāng)然,opencv可能只是為了開發(fā)一個(gè)足夠庫(kù)自身使用的內(nèi)存管理與動(dòng)態(tài)數(shù)據(jù)結(jié)構(gòu)而已。就這個(gè)需求來(lái)說(shuō),opencv是達(dá)到了。


            但"足夠庫(kù)自身使用"不一定就能滿足用戶的所有需求。
            而opencv也不提供任何方法讓用戶擴(kuò)展它的庫(kù)。
            從這方面來(lái)說(shuō),opencv是相當(dāng)?shù)氖竽看绻狻?br>

            比如opencv提供的CvCapture。其內(nèi)部是有一個(gè)C實(shí)現(xiàn)的capture接口與capture工廠。
            可是它不將接口定義暴露給用戶。
            用戶需要自己的capture時(shí)怎么辦? 等著opencv去支持嗎? 那是不可能的。只能自己動(dòng)手。
            這個(gè)需求還好, 大不了讓自己的capture返回image(image or matrix),然后丟給opencv去處理就可以了。
            image的格式opencv還算厚道,暴露出來(lái)了。
            用戶如果想要實(shí)現(xiàn)得好一些,更c(diǎn)apture無(wú)關(guān),就需要自己再抽象一個(gè)capture接口,然后將opencv的capture包含進(jìn)去 —— 基本就是將CvCapture的代碼再實(shí)現(xiàn)一遍 —— 因?yàn)槟嵌桃暤膐pencv沒將這個(gè)可擴(kuò)展點(diǎn)暴露出來(lái)。



            如果用戶不滿意CvMemStorage和CvSeq的行為,哼哼……
            必須屈服,除非用戶想自己重寫opencv —— 換句話說(shuō),就是放棄opencv。

            CvMemStorage實(shí)現(xiàn)的是一個(gè)"多次取、整體放"的策略。
            所有的動(dòng)態(tài)數(shù)據(jù)結(jié)構(gòu)都將數(shù)據(jù)存放在CvMemStorage分配的內(nèi)存上。
            沒有單獨(dú)釋放數(shù)據(jù)結(jié)構(gòu)中某個(gè)元素的方式,只能釋放整個(gè)Storage。
            可是opencv沒有定義出一個(gè)接口,作為CvMemStorage和CvSeq之間的中間層,而是CvSeq直接使用CvMemStorage。

            CvMemStorage本身也不咋嘀。甚至還有一個(gè)單次分配大小的上限……

            一句話,opencv需要輸出動(dòng)態(tài)數(shù)據(jù)結(jié)構(gòu)的算法和CvSeq綁死了,CvSeq又和CvMemStorage綁死了,而CvMemStorage又實(shí)現(xiàn)得不咋嘀……
            你要使用opencv嗎?請(qǐng)忍受CvMemStorage……
            相比CvCapture可以繞過(guò)去;這個(gè)問(wèn)題幾乎無(wú)解。

              回復(fù)  更多評(píng)論   

            # re: 散列3 2009-11-27 20:41 小羅羅

            @OwnWaterloo
            謝謝您指點(diǎn),因?yàn)槲乙郧爸皇怯眠^(guò)opencv里的函數(shù),從沒有關(guān)心它的實(shí)現(xiàn),我的打算是通過(guò)學(xué)習(xí)它的內(nèi)存機(jī)制來(lái)加深對(duì)它內(nèi)部結(jié)構(gòu)的了解,并且我現(xiàn)在還在用一個(gè)叫mil的庫(kù),它不是開源的,相比較而言,我就選擇opencv來(lái)學(xué)習(xí),不管怎樣,我覺得opencv還是值得我現(xiàn)在的水平拿來(lái)學(xué)習(xí)的,只有真正學(xué)過(guò)了,才有資格評(píng)論,是吧?  回復(fù)  更多評(píng)論   

            # re: 散列3 2009-11-27 20:56 OwnWaterloo

            @小羅羅
            只看源碼很枯燥,而且有些細(xì)節(jié)很難理解。
            看這本書吧:《C語(yǔ)言接口與實(shí)現(xiàn):創(chuàng)建可重用軟件的技術(shù)》
            http://www.china-pub.com/14974

            里面的arena,思想和CvMemStorage是一樣的"零取整放"。
            CvMemStorage比arena多一些功能。

            書里將arena的同時(shí),會(huì)把內(nèi)存分配器的一些細(xì)節(jié)說(shuō)清楚,這些可能是看源代碼多遍都看不出來(lái)的。
            反正arena章節(jié)也不多……

              回復(fù)  更多評(píng)論   

            # re: 散列3 2009-11-27 23:44 小羅羅

            看了簡(jiǎn)介,很不錯(cuò)的樣子,好的,聽你的,豁出去了,買了  回復(fù)  更多評(píng)論   

            # re: 散列3 2009-11-27 23:50 OwnWaterloo

            @小羅羅
            這…… 那鏈接上不是說(shuō)已經(jīng)絕版了嗎?
              回復(fù)  更多評(píng)論   

            # re: 散列3 2009-11-27 23:52 OwnWaterloo

            http://download.csdn.net/source/747860

            掃描版的,湊合著看吧……
            源代碼在這里:
            http://code.google.com/p/cii/downloads/list

              回復(fù)  更多評(píng)論   

            # re: 散列3 2009-11-28 00:00 小羅羅

            OwnWaterloo ,我下載下來(lái)了,現(xiàn)在開始看。


              回復(fù)  更多評(píng)論   


            只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。
            網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問(wèn)   Chat2DB   管理


            導(dǎo)航

            統(tǒng)計(jì)

            常用鏈接

            留言簿

            隨筆檔案

            搜索

            最新評(píng)論

            • 1.?re: 老外談future of c++
            • 評(píng)論內(nèi)容較長(zhǎng),點(diǎn)擊標(biāo)題查看
            • --loan
            • 2.?re: 老外談future of c++
            • Do not realize the way to save your thoughts from thefts? I recommend to use plagiarism check.
            • --check for plagiarism
            • 3.?re: 老外談future of c++
            • 評(píng)論內(nèi)容較長(zhǎng),點(diǎn)擊標(biāo)題查看
            • --CLAUDETTEMOODY
            • 4.?re: 散列3
            • OwnWaterloo ,我下載下來(lái)了,現(xiàn)在開始看。


            • --小羅羅
            • 5.?re: 散列3
            • 評(píng)論內(nèi)容較長(zhǎng),點(diǎn)擊標(biāo)題查看
            • --OwnWaterloo

            閱讀排行榜

            評(píng)論排行榜

            久久九九免费高清视频| 久久久精品人妻一区二区三区四| 综合网日日天干夜夜久久| 狠狠人妻久久久久久综合| 国内精品伊人久久久久av一坑| 亚洲国产视频久久| 欧美午夜A∨大片久久 | 国产精品99久久99久久久| 久久精品成人| 久久综合九色欧美综合狠狠| 国产呻吟久久久久久久92| 激情综合色综合久久综合| 成人精品一区二区久久久| 久久国产精品99久久久久久老狼| 狠狠色丁香婷婷综合久久来| 久久亚洲精品中文字幕三区| A级毛片无码久久精品免费| 狠狠色综合网站久久久久久久| 久久精品国产99久久久香蕉| 人妻系列无码专区久久五月天| 亚洲午夜精品久久久久久浪潮| 亚洲欧洲中文日韩久久AV乱码| 无码人妻久久一区二区三区蜜桃| 亚洲va中文字幕无码久久不卡 | AA级片免费看视频久久| 久久久久亚洲AV无码去区首| 大香伊人久久精品一区二区| 久久久国产精品亚洲一区| 草草久久久无码国产专区| 性做久久久久久久久浪潮| 久久久久99精品成人片试看| 久久精品国产一区二区三区不卡| 久久久无码精品亚洲日韩京东传媒| 人妻精品久久无码区| 精品久久久久久国产牛牛app| 国产精品久久久久久久app| 久久97精品久久久久久久不卡| 久久久噜噜噜久久中文字幕色伊伊| 久久久国产精华液| 天天久久狠狠色综合| 中文字幕乱码人妻无码久久|