雜湊表—-在VOIP使用者資訊儲存中的應用

來源:互聯網
上載者:User
文章目錄
  •   對雜湊表的使用者一一人來說,這是一瞬間的事。雜湊表運算得非常快,在電腦程式中,如果需要在一秒種內尋找上千條記錄通常使用雜湊表(例如拼字檢查器)雜湊表的速度明顯比樹快,樹的操作通常需要O(N)的時間級。雜湊表不僅速度快,編程實現也相對容易。
  •   雜湊表也有一些缺點它是基於數組的,數組建立後難於擴充某些雜湊表被基本填滿時,效能下降得非常嚴重,所以程式雖必須要清楚表中將要儲存多少資料(或者準備好定期地把資料轉移到更大的雜湊表中,這是個費時的過程)。
  •   而且,也沒有一種簡便的方法可以以任何一種順序〔例如從小到大〕遍曆表中資料項目。如果需要這種能力,就只能選擇其他資料結構。
  • 然而如果不需要有序遍曆資料,井且可以提前預測資料量的大小。那麼雜湊表在速度和易用性方面是無與倫比的。
  •   下面在雜湊表在SIP電話中用於儲存當前在前使用者的資訊(使用者資訊已經在初始化是儲存在全域變數的一個鏈表中,文中有說明,線上使用者需要時刻和控制台進行互動(比如通話、佔線)所有要求速度快),廢話不多說直接分析代碼吧~
  雜湊表是種資料結構,它可以提供快速的插入操作和尋找操作。第一次接觸雜湊表時,它的優點多得讓人難以置信。不論雜湊表中有多少資料,插入和刪除(有時包括側除)只需要接近常量的時間即0(1)的時間級。實際上,這隻需要幾條機器指令。  對雜湊表的使用者一一人來說,這是一瞬間的事。雜湊表運算得非常快,在電腦程式中,如果需要在一秒種內尋找上千條記錄通常使用雜湊表(例如拼字檢查器)雜湊表的速度明顯比樹快,樹的操作通常需要O(N)的時間級。雜湊表不僅速度快,編程實現也相對容易。  雜湊表也有一些缺點它是基於數組的,數組建立後難於擴充某些雜湊表被基本填滿時,效能下降得非常嚴重,所以程式雖必須要清楚表中將要儲存多少資料(或者準備好定期地把資料轉移到更大的雜湊表中,這是個費時的過程)。  而且,也沒有一種簡便的方法可以以任何一種順序〔例如從小到大〕遍曆表中資料項目。如果需要這種能力,就只能選擇其他資料結構。然而如果不需要有序遍曆資料,井且可以提前預測資料量的大小。那麼雜湊表在速度和易用性方面是無與倫比的。  下面在雜湊表在SIP電話中用於儲存當前在前使用者的資訊(使用者資訊已經在初始化是儲存在全域變數的一個鏈表中,文中有說明,線上使用者需要時刻和控制台進行互動(比如通話、佔線)所有要求速度快),廢話不多說直接分析代碼吧~

標頭檔:

#ifndef _HASH_H#define _HASH_H#define OK 1#define ERROR 0#define HASH_SIZE             256typedef struct _hashNode /*採用雙向鏈表格儲存體*/{struct _hashNode * next;struct _hashNode * prev;} tHashNode;tHashNode * vSipUserLocation[ HASH_SIZE ];/*槽*/#endif

雜湊表演算法(字串處理)

int hashString (const char *str){    unsigned int h=0;    int len;    int i;    len = strlen(str);    if (len <= 0 || len > HASH_SIZE)        return -1;    for (i = 0; i < len; i++) {        h = ( h << 5 ) - h + *(str + i);    }    return h % HASH_SIZE;}雜湊槽的初始化int hashInit(tHashNode **pList, unsigned int size){        if ( !pList )        return ERROR;        memset(pList, '\0', size);    return OK;}
插入節點int  hashAddNode ( tHashNode ** pList,  tHashNode * pNode,  char *hash, func  pCmpFunc  ) {    int index;    tHashNode *tempNode = NULL;    int ret;    if ( !pList || !pNode || !hash )        return ERROR;     index = hashString( hash ) ;    if ( index < 0 )        return ERROR;    /* 首個節點     */    tempNode =  pList [ index ] ;    if( !tempNode ) {         pList [ index ] = pNode;        pNode->next = NULL ;        pNode->prev = NULL;        return OK ;    }    /* 遍曆是否有相同的節點 函數Pcmpfunc()是比較指標是否指向相同的記憶體位址*/    if( pCmpFunc ) {        for( ; tempNode != NULL ; tempNode = tempNode->next )        {            if((ret = pCmpFunc(tempNode, pNode, 0)) == 0)                break;        }         if ( ret == 0 )            return OK ;    }    /*為找到相同的節點,插入到第一個節點位置 */    tempNode = pList [ index ] ;    pList [ index ]  = pNode ;    pNode->next = tempNode;    pNode->prev = NULL;    tempNode->prev = pNode;     return OK ;}
 關於插入節點中的參數應用,在代碼中調用函數如下:
typedef struct _Callee {    tHashNode pNode;    char name[24];    struct _Callee *next;}Callee
 Callee *p ;p 是指向一個全域變數 (鏈表,存放系統設定的所有使用者的資訊)中的一個節點,儲存使用者資訊(我這裡進行了修改,只顯示一部分內容)。而雜湊表存放的是當前線上使用者,當使用者註冊是需要加入雜湊表中。hashAddNode(vSipUserLocation, (tHashNode *)p, p->name, issamecallee)

下面是和別人溝通:

A:

這個問題我也遇到了,因為tSipCallee *p ,這個p指向的是儲存tSipCalle結構的記憶體位址,這個地址指向的記憶體是一塊連續的空間,比如大小是n,那麼我們可以很隨意的取這n個位元組中的一段內容,也就是說sizeof(tHashNode)<=sizeof(Callee),把n中的前m(<=n)個位元組當成tHashNode 的內容,也就是說可以把這m個位元組當成一個tHashNode結構體
但是如果sizeof(tHashNode)>sizeof(Callee),那就不行了,會造成訪問越界的情況B:定義這個結構體的時候已經包含這個 tHasgNode pNode;
太抽象了~

A:對哈,我給你畫個圖你就明白了B:看來你看得挺多了,剛開始我迷糊在(tHashNode *)p ,強制類型轉換,不就把P中前2個位元組內容覆蓋掉了!A:你看看這個結構,tSipCallee在記憶體中的存放方法,強制轉換的意思就是“我”只想使用前一段位元組:sizeof(tHashNode),後面是什麼我不管。通過data尋找節點

tHashNode * hashGetNode(tHashNode ** pList, char *hash,  func  pCmpFunc, void * cmpArg){    int index;    tHashNode *tempNode = NULL;    if ( !pList ||  !hash || !pCmpFunc )        return NULL;    index = hashString( hash ) ;    if ( index < 0 )        return NULL;    tempNode =  pList [ index ] ;    while (tempNode ) {/*尋找參數 cmoArg是否在節點tempNode中儲存)        if ( pCmpFunc ( tempNode, NULL, cmpArg ) == 0 ) {            break;        }        tempNode = tempNode->next;    }    return tempNode;}

獲得當前列內容:

  

tHashNode * hashGetSlot(tHashNode ** pList, const char *hash ){    int index;    if ( !pList || !hash )        return NULL;    index = hashString( hash );    if( index < 0 )        return NULL;    return pList[ index ];}

刪除節點

int hashRemoveNode(tHashNode ** pList, tHashNode * pNode, char *hash){    int index;        if ( !pList || !pNode || !hash )        return ERROR ;     index = hashString( hash ) ;    if ( index < 0 )        return ERROR;      if(!pNode->prev) { /* 第一個節點 */        pList[index] = pNode->next;        if(pNode->next)            pNode->next->prev = NULL;    }else if ( !pNode->next ) { /* 下一個節點 */        pNode->prev->next = NULL;    }else {        pNode->prev->next = pNode->next;        pNode->next->prev = pNode->prev;    }    return OK;}

雜湊表是處理大量資料中因處理速度比較快,應用非常廣泛。但是也不難理解,只有認真閱讀代碼,

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.