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

            無我

            讓內(nèi)心永遠燃燒著偉大的光明的精神之火!
            靈活的思考,嚴謹?shù)膶崿F(xiàn)
            豪邁的氣魄、頑強的意志和周全的思考

            剖析eSNACC哈希結(jié)構(gòu)的設(shè)計和實現(xiàn)

            本文剖析hash.h/c,從源代碼來剖析eSNACC哈希結(jié)構(gòu)的設(shè)計和實現(xiàn)。 

            為什么要在這里剖析hash呢?一個順理成章的理由是:我們準(zhǔn)備剖析eSNACC對ANY(s)類型的編碼和解碼,可是ANY的實現(xiàn)依賴于hash,所以我們就需要先把這條路打通了。O(∩_∩)O哈哈~是不是很有說服力呀?

             

            好,閑話少述,言規(guī)正傳。我們知道hash對一個系統(tǒng)而言,一般都是一個很有價值的底層基礎(chǔ)設(shè)施。從作用上來說,他實現(xiàn)的優(yōu)劣極大的影響著整個系統(tǒng)的性能。從技術(shù)上來說,也是很能體現(xiàn)含金量的一個模塊。所以,對eSNACC實現(xiàn)的這個寶藏,我們下定決心要刨根問底、直搗黃龍!

             

            友情說明:本文不討論eSNACC用的hash函數(shù),因為我們用了另外獨立的一篇文章來研究:剖析eSNACC的hash函數(shù)。本文研究的是eSNACC哈希結(jié)構(gòu)的設(shè)計和實現(xiàn)。

             

            先看頭文件:

            #ifndef _asn_hash_h_
            #define _asn_hash_h_

            #ifdef __cplusplus
            extern "C" {
            #endif


            #define TABLESIZE 256
            #define INDEXMASK 0xFF
            #define INDEXSHIFT 8

            typedef 
            void *Table[TABLESIZE];

            typedef unsigned 
            int Hash;

            typedef 
            struct HashSlot
            {
              
            int    leaf;
              Hash   hash;
              
            void  *value;
              Table 
            *table;
            }
             HashSlot;

            Hash MakeHash PROTO ((
            char *str, unsigned long  len));

            Table 
            *InitHash();

            int Insert PROTO ((Table *table, void *element, Hash hash));

            int CheckFor PROTO ((Table *table, Hash hash));

            int CheckForAndReturnValue PROTO ((Table *table, Hash hash, void **value));

            #ifdef __cplusplus
            }

            #endif

            #endif /* conditional include */

            在這里,就利用這個頭文件,我想先和大家講清楚eSNACC的hash表的設(shè)計結(jié)構(gòu)。

            首先,eSNACC的每一個hash值用unsigned int來定義:typedef unsigned int Hash。

            然后,定義的hash表結(jié)構(gòu)——Table:typedef void *Table[TABLESIZE],是一個256維的指針數(shù)組。

            那這個數(shù)組每個元素的內(nèi)容是什么呢?是指向HashSlot結(jié)構(gòu)的指針,也就是這個hash表的每一維是一個HashSlot。但是如果這樣,只能存放256個值呀,怎樣實現(xiàn)hash的呢?這個我們就要理解HashSlot的各個變量的意義了:

            int    leaf : 當(dāng)前HashSlot是不是樹的葉子。
            Hash   hash :當(dāng)前HashSlot元素的hash值。
            void  *value :對應(yīng)當(dāng)前hash值元素內(nèi)容,也就是實際值。
            Table *table :如果當(dāng)前HashSlot不是葉子,也就是說在當(dāng)前hash有多個共用的元素,那么本字段就不為空,而是指向再次hash的表。

            我做了一張簡單的示意圖來描述:

            雖然不美觀,但還是希望你能從中看明白這個hash表的結(jié)構(gòu)哦。

             

             

            /******************************休息一下************************************

            好了,有了對整個hash表設(shè)計的理解,我們就來研究具體的hash表操作函數(shù)

            /* Creates and clears a new hash slot */
            static HashSlot * NewHashSlot()
            {
              HashSlot 
            *foo;

              foo 
            =  new HashSlot;
              
            if (foo == NULL)
                  
            return NULL;
              memset (foo, 
            0sizeof (HashSlot));
              
            return foo;
            }


            /* Create a new cleared hash table */
            static Table *NewTable()
            {
              Table 
            *new_table;

            //  new_table = new Table;
            // whose bug is it that gcc won't compile the above line?
              new_table = (Table *new Table;
              
            if (new_table == NULL)
                  
            return NULL;
              memset (new_table, 
            0sizeof (Table));
              
            return new_table;
            }


            /* This routine is used to initialize the hash tables. When it is called
             * it returns a value which is used to identify which hash table
             * a particular request is to operate on.
             
            */

            Table 
            * InitHash()
            {
              Table 
            *table;
              table 
            = NewTable();
              
            if (table == NULL)
                  
            return 0;
              
            else
                  
            return table;
            }

            上面三個很簡單,前兩個調(diào)用new創(chuàng)建HashSlot和Table,第三個就是用來初始最上層hash表的函數(shù)。

             

            下面我們來看看將一個hash值為hash_value的元素element插入到哈希表table的具體實現(xiàn):

            /* This routine takes a hash table identifier, an element (value) and the
             * coresponding hash value for that element and enters it into the table
             * assuming it isn't already there.
             
            */

            int Insert (Table *table, void *element, Hash hash_value)
            {
              HashSlot 
            *entry;

              entry 
            = (HashSlot *) (*table)[hash_value & INDEXMASK];

              
            if (entry == NULL) {
                
            /* Need to add this element here */
                entry 
            = NewHashSlot();
                
            if (entry == NULL)
                    
            return false;
                entry
            ->leaf = true;
                entry
            ->value = element;
                entry
            ->hash = hash_value;
                (
            *table)[hash_value & INDEXMASK] = entry;
                
            return true;
              }


              
            if (hash_value == entry->hash)
                  
            return false;

              
            if (entry->leaf)
                  
            return SplitAndInsert (entry, element, hash_value);

              
            return Insert (entry->table, element, hash_value >> INDEXSHIFT);
            }

            函數(shù)利用hash_value的最后一個字節(jié)來判斷該元素應(yīng)該放在table中的維數(shù),并且取出該維對應(yīng)的HashSlot entry。

            如果entry為空,那么也就是對應(yīng)該hash_value還沒有元素,可以直接創(chuàng)建HashSlot,設(shè)定entry的value為element,hash為hash_value,因為當(dāng)前只有這一個值,所以本HashSlot就是葉子,其table成員也為空。然后將該新的entry連到table的對應(yīng)維上,完成。

            如果entry不為空,依次判斷以下三種情況:

            1、如果當(dāng)前entry的hash等于hash_value,那就是hash值沖突,直接返回false。

            2、如果當(dāng)前entry是葉子,那么就得拆分當(dāng)前HashSlot,使得他用table來存放多個值。

            3、如果entry不是葉子了,那么就將本元素插到entry->table里面。

            我們看一下SplitAndInsert:

            /* When a hash collision occurs at a leaf slot this routine is called to
             * split the entry and add a new level to the tree at this point.
             
            */

            static int SplitAndInsert (HashSlot *entry, void *element, Hash hash_value)
            {

              
            if (((entry->table = NewTable()) == NULL) ||
                  
            !Insert (entry->table, entry->value, entry->hash >> INDEXSHIFT) ||
                  
            !Insert (entry->table, element, hash_value >> INDEXSHIFT))
                
            return false;

              entry
            ->leaf = false;
              
            return true;
            }

            恩,很清楚,首先為entry的table分配一個Table,接著再將entry中原來存的值(entry->vlaue,entry->hash)插到表里,然后還將新加入的值(element,hash_value)插入表里。最后將entry的葉子屬性改為非葉子。

            注意:在級聯(lián)的hash表里存的不是原來的hash值,而是依次將hash>>8.也就是出了最高層的哈希表,其他的都依次去掉最末尾的一個字節(jié)!!!

             

            我們模擬插入兩個元素,假設(shè)其值和hash分別為A("tim",0xAA02),B("eSNACC",0xBB02).只是為了說明,我們假設(shè)原始table為空:

            1,插入A:hash_value=0xAA02,所以應(yīng)當(dāng)插入到table的第三維,插入以后應(yīng)當(dāng)為:

            2.插入B:hash_value=0xBB02,hash_value & 0xFF=2,所以又找到第三位,然后此時有HashSlot葉子,所以需要拆分,在插入后應(yīng)當(dāng)為:

            利用這兩個圖,應(yīng)該說得很清楚了吧,還是圖最清楚了!O(∩_∩)O哈哈~

             

            好了,讓我們來看最后兩個函數(shù):

            /* This routine looks to see if a particular hash value is already stored in
             * the table. It returns true if it is and false otherwise.
             
            */

            int CheckFor (Table *table, Hash hash)
            {
              HashSlot 
            *entry;

              entry 
            = (HashSlot *) table[hash & INDEXMASK];

              
            if (entry == NULL)
                  
            return false;
              
            if (entry->leaf)
                  
            return entry->hash == hash;
              
            return CheckFor (entry->table, hash >> INDEXSHIFT);
            }


            /* In addition to checking for a hash value in the tree this function also
             * returns the coresponding element value into the space pointed to by
             * the value parameter. If the hash value isn't found false is returned
             * the the space pointed to by value is not changed.
             
            */

            int CheckForAndReturnValue (Table *table, Hash hash, void **value)
            {
              HashSlot 
            *entry;
              
            if (table)
              
            {
                  entry 
            = (HashSlot *) (*table)[hash & INDEXMASK];

                  
            if (entry == NULL)
                      
            return false;

                  
            if (entry->leaf)
                  
            {
                      
            if (entry->hash == hash)
                      
            {
                          
            *value = entry->value;
                          
            return true;
                      }

                      
            else
                          
            return false;
                  }

                  
            return CheckForAndReturnValue (entry->table, hash >> INDEXSHIFT, value);
              }

              
            else
                 
            return false;
            }

            這兩個函數(shù)功能很清晰,就是在給定的哈希表table查找對應(yīng)哈希值為hash的元素。只是CheckFor只是檢查table存在此hash否。而CheckForAndReturnValue則在存在時,將元素值存在value中返回。

             

            好了,到此,eSNACC哈希結(jié)構(gòu)的設(shè)計就已經(jīng)全部分析完成了!祝大家學(xué)習(xí)愉快~

            posted on 2012-04-26 15:36 Tim 閱讀(1759) 評論(1)  編輯 收藏 引用 所屬分類: eSNACC學(xué)習(xí)

            評論

            # re: 剖析eSNACC哈希結(jié)構(gòu)的設(shè)計和實現(xiàn)[未登錄] 2012-04-27 09:31 Tina

            寫的很好,圖的增加讓人很好理解。等待你的新作品!  回復(fù)  更多評論   

            <2007年10月>
            30123456
            78910111213
            14151617181920
            21222324252627
            28293031123
            45678910

            導(dǎo)航

            統(tǒng)計

            公告

            本博客原創(chuàng)文章,歡迎轉(zhuǎn)載和交流。不過請注明以下信息:
            作者:TimWu
            郵箱:timfly@yeah.net
            來源:www.shnenglu.com/Tim
            感謝您對我的支持!

            留言簿(9)

            隨筆分類(173)

            IT

            Life

            搜索

            積分與排名

            最新隨筆

            最新評論

            閱讀排行榜

            久久久噜噜噜久久中文字幕色伊伊| 国产成人精品久久一区二区三区av| 久久久WWW免费人成精品| 亚洲国产精品久久久久网站| 一本大道久久a久久精品综合| 国内精品久久久久久不卡影院| 久久婷婷色综合一区二区| 久久久青草青青国产亚洲免观| 亚洲中文久久精品无码| 久久精品国产亚洲欧美| 一本大道久久香蕉成人网| 久久夜色精品国产噜噜亚洲AV| 久久99国产精品成人欧美| 亚洲va中文字幕无码久久不卡 | 国内精品久久久久久不卡影院| 久久亚洲精品国产亚洲老地址| 青青草原综合久久大伊人精品| 国产精品久久久久久久久软件| 欧美亚洲另类久久综合| 亚洲国产一成人久久精品| 久久精品国产精品亚洲艾草网美妙 | 久久精品草草草| 久久WWW免费人成一看片| 一级做a爰片久久毛片免费陪| 成人亚洲欧美久久久久| 97久久精品无码一区二区| 久久精品国产亚洲AV香蕉| 久久精品国产亚洲av麻豆图片| 欧美大战日韩91综合一区婷婷久久青草| 色综合久久久久久久久五月| 中文成人无码精品久久久不卡| 草草久久久无码国产专区| 四虎影视久久久免费观看| 欧美久久亚洲精品| 日本精品久久久久中文字幕| 久久777国产线看观看精品| 国产精品久久99| 99久久成人国产精品免费| 久久国产精品-国产精品| 精品国产综合区久久久久久 | 久久综合噜噜激激的五月天|