日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

哈希表,哈希算法(C语言)

發布時間:2025/3/15 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 哈希表,哈希算法(C语言) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

哈希表

哈希表,又稱散列表,常用于在海量數據中查找數據

哈希表中元素是由哈希函數確定的。將數據元素的關鍵字key作為自變量,通過一定的函數關系H(稱為哈希函數),計算出的值,即為該元素的存儲地址。其優點是:運算速度快;缺點是:基于數組、難于擴展,不可遍歷。

在建立一個哈希表之前需要解決兩個主要問題:

  • 構造均勻的哈希函數
    使H(key)均勻分布在哈希表中,以提高地址計算的速度。
    構造哈希函數的方法:直接定址法,數字分析法,平法折中法,折疊法,除留余數法,隨機數法等。
  • 處理沖突
    沖突是指在哈希表中,不同的關鍵字值對應到同一個存儲位置的現象。即存在K1≠K2,但H(K1)=H(K2)。
    再均勻的哈希函數都只能可減少沖突,但不可能避免沖突。
    發生沖突后,必須解決,即必須尋找下一個可用地址。
    解決沖突的方法:開放地址法(包括線性探測,二次探測,隨機探測),再哈希法,鏈地址法,建立公共溢出區等。
  • C語言實現

    哈希表的數據結構

    typedef struct HashNode_Struct HashNode; struct HashNode_Struct { char* sKey;//鍵值指針int nValue; //鍵值HashNode* pNext; //指向下一個哈希結構 };

    定義最大哈希長度及哈希數組

    #define HASH_TABLE_MAX_SIZE 10000 HashNode* hashTable[HASH_TABLE_MAX_SIZE]; //哈希數組 int hash_table_size; //當前哈希長度

    哈希表初始化函數

    void hash_table_init() { hash_table_size = 0; memset(hashTable, 0 , sizeof(HashNode*) * HASH_TABLE_MAX_SIZE);//memset(void *s,int c,size_t n); //將s中后n個字節換成c所代表的內容 //該函數是對較大結構體或數組進行清零操作的一種最快的方法 }

    去符號化函數

    unsigned int hash_table_hash_str(const char* skey) { //無符號unsigned能保存2倍與有符號類型的正整型數據 const signed char *p = (const signed char*)skey; //常量 unsigned int h = *p; if(h){ for(p += 1; *p != '\0'; ++p) h = (h << 5) - h + *p; } return h; }

    插入函數

    void hash_table_insert(const char* skey, int nvalue) { if(hash_table_size >= HASH_TABLE_MAX_SIZE) //如果定義的哈希表長度大于等于最大長度 { printf("內存溢出!\n");return; } unsigned int pos = hash_table_hash_str(skey) % HASH_TABLE_MAX_SIZE; //用于解決沖突,pos為哈希函數 HashNode* pHead = hashTable[pos];while(pHead){ if(strcmp(pHead->sKey, skey) == 0) { printf("%s發生沖突!\n", skey);return ; } pHead = pHead->pNext; } //動態建立結點,初始化,分配內存空間 HashNode* pNewNode = (HashNode*)malloc(sizeof(HashNode)); memset(pNewNode, 0, sizeof(HashNode)); pNewNode->sKey = (char*)malloc(sizeof(char) * (strlen(skey) + 1)); strcpy(pNewNode->sKey, skey); pNewNode->nValue = nvalue; //指針后移 pNewNode->pNext = hashTable[pos]; hashTable[pos] = pNewNode; //表長增加 hash_table_size++; }

    刪除函數

    void hash_table_remove(const char* skey) { unsigned int pos = hash_table_hash_str(skey) % HASH_TABLE_MAX_SIZE; if(hashTable[pos]) { HashNode* pHead = hashTable[pos]; HashNode* pLast = NULL; HashNode* pRemove = NULL; while(pHead) { if(strcmp(skey, pHead->sKey) == 0) { //若str1==str2,則返回零;//若str1>str2,則返回正數;//若str1<str2,則返回負數。 pRemove = pHead;//若相等,用pRemove記錄 break; } pLast = pHead; //若不相等,不斷后移 pHead = pHead->pNext; } if(pRemove) { if(pLast)pLast->pNext = pRemove->pNext;//實現刪除1 else hashTable[pos] = NULL;//實現刪除2free(pRemove->sKey); free(pRemove); } } }

    查找函數

    HashNode* hash_table_lookup(const char* skey) { unsigned int pos = hash_table_hash_str(skey) % HASH_TABLE_MAX_SIZE; if(hashTable[pos]) { HashNode* pHead = hashTable[pos]; while(pHead) { if(strcmp(skey, pHead->sKey) == 0) return pHead;//查找成功 pHead = pHead->pNext; } } return NULL; }

    打印哈希表函數

    void hash_table_print() { int i; for(i = 0; i < HASH_TABLE_MAX_SIZE; ++i) if(hashTable[i])//表不空 { HashNode* pHead = hashTable[i]; printf("%d=>", i); while(pHead) { printf("%s:%d ", pHead->sKey, pHead->nValue); pHead = pHead->pNext; } printf("\n"); } }

    釋放內存函數

    void hash_table_release() { int i; for(i = 0; i < HASH_TABLE_MAX_SIZE; ++i) { if(hashTable[i]) { HashNode* pHead = hashTable[i]; while(pHead) { HashNode* pTemp = pHead; pHead = pHead->pNext; if(pTemp) { free(pTemp->sKey); free(pTemp); } //逐個釋放 } } } }

    隨機生成函數

    #define MAX_STR_LEN 20 #define MIN_STR_LEN 10 void rand_str(char r[]) { int i; int len = MIN_STR_LEN + rand() % (MAX_STR_LEN - MIN_STR_LEN); for(i = 0; i < len - 1; ++i) r[i] = 'a' + rand() % ( 'z' - 'a'); r[len - 1] = '\0'; }

    具體代碼如下:

    #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> #define HASH_TABLE_MAX_SIZE 10000 typedef struct HashNode_Struct HashNode; struct HashNode_Struct { char* sKey; int nValue; HashNode* pNext; }; //哈希表數據結構 HashNode* hashTable[HASH_TABLE_MAX_SIZE]; int hash_table_size; //哈希表中鍵值對的數量 //初始化哈希表 void hash_table_init() { hash_table_size = 0; memset(hashTable, 0, sizeof(HashNode*) * HASH_TABLE_MAX_SIZE);//memset(void *s,int c,size_t n); //將s中后n個字節換成c所代表的內容 //該函數是對較大結構體或數組進行清零操作的一種最快的方法 } //去符號化哈希表 unsigned int hash_table_hash_str(const char* skey) { //無符號unsigned能保存2倍與有符號類型的正整型數據 const signed char *p = (const signed char*)skey; //常量 unsigned int h = *p; if(h){ for(p += 1; *p != '\0'; ++p) h = (h << 5) - h + *p; } return h; } //插入 void hash_table_insert(const char* skey, int nvalue) { if(hash_table_size >= HASH_TABLE_MAX_SIZE) //如果定義的哈希表長度大于等于最大長度 { printf("內存溢出!\n");return; } unsigned int pos = hash_table_hash_str(skey) % HASH_TABLE_MAX_SIZE; //用于解決沖突,pos為哈希函數 HashNode* pHead = hashTable[pos];while(pHead){ if(strcmp(pHead->sKey, skey) == 0) { printf("%s發生沖突!\n", skey);return ; } pHead = pHead->pNext; } //動態建立結點,初始化,分配內存空間 HashNode* pNewNode = (HashNode*)malloc(sizeof(HashNode)); memset(pNewNode, 0, sizeof(HashNode)); pNewNode->sKey = (char*)malloc(sizeof(char) * (strlen(skey) + 1)); strcpy(pNewNode->sKey, skey); pNewNode->nValue = nvalue; //指針后移 pNewNode->pNext = hashTable[pos]; hashTable[pos] = pNewNode; //表長增加 hash_table_size++; } //刪除 void hash_table_remove(const char* skey) { unsigned int pos = hash_table_hash_str(skey) % HASH_TABLE_MAX_SIZE; if(hashTable[pos]) { HashNode* pHead = hashTable[pos]; HashNode* pLast = NULL; HashNode* pRemove = NULL; while(pHead) { if(strcmp(skey, pHead->sKey) == 0) { //若str1==str2,則返回零;//若str1>str2,則返回正數;//若str1<str2,則返回負數。 pRemove = pHead;//若相等,用pRemove記錄 break; } pLast = pHead; //若不相等,不斷后移 pHead = pHead->pNext; } if(pRemove) { if(pLast)pLast->pNext = pRemove->pNext;//實現刪除1 else hashTable[pos] = NULL;//實現刪除2free(pRemove->sKey); free(pRemove); } } } //查找 HashNode* hash_table_lookup(const char* skey) { unsigned int pos = hash_table_hash_str(skey) % HASH_TABLE_MAX_SIZE; if(hashTable[pos]) { HashNode* pHead = hashTable[pos]; while(pHead) { if(strcmp(skey, pHead->sKey) == 0) return pHead;//查找成功 pHead = pHead->pNext; } } return NULL; } //打印 void hash_table_print() { int i; for(i = 0; i < HASH_TABLE_MAX_SIZE; ++i) if(hashTable[i])//表不空 { HashNode* pHead = hashTable[i]; printf("%d=>", i); while(pHead) { printf("%s:%d ", pHead->sKey, pHead->nValue); pHead = pHead->pNext; } printf("\n"); } } //釋放內存 void hash_table_release() { int i; for(i = 0; i < HASH_TABLE_MAX_SIZE; ++i) { if(hashTable[i]) { HashNode* pHead = hashTable[i]; while(pHead) { HashNode* pTemp = pHead; pHead = pHead->pNext; if(pTemp) { free(pTemp->sKey); free(pTemp); } //逐個釋放 } } } } /* ============================主測試函數============================*/ #define MAX_STR_LEN 20 #define MIN_STR_LEN 10 void rand_str(char r[]) { int i; int len = MIN_STR_LEN + rand() % (MAX_STR_LEN - MIN_STR_LEN); for(i = 0; i < len - 1; ++i) r[i] = 'a' + rand() % ( 'z' - 'a'); r[len - 1] = '\0'; } int main(int argc, char** argv) { srand(time(NULL)); hash_table_init(); int n = 10; char str[MAX_STR_LEN + 1]; const char *key1 = "aaa111"; const char *key2 = "bbb222"; const char *key3 = "ccc333";while(n--) { rand_str(str); hash_table_insert(str, n); }printf("插入前\n");hash_table_print(); hash_table_insert(key1, 1); hash_table_insert(key2, 2); hash_table_insert(key3, 2); printf("插入后\n");hash_table_print(); HashNode* pNode = hash_table_lookup(key1); printf("查找結果:%d\n", pNode->nValue); pNode = hash_table_lookup(key2); printf("查找結果:%d\n", pNode->nValue);printf("刪除之前:\n"); hash_table_print(); hash_table_remove(key3); printf("刪除之后:\n"); hash_table_print(); hash_table_release(); return 0; }

    總結

    以上是生活随笔為你收集整理的哈希表,哈希算法(C语言)的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。