最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C語言寫一個(gè)散列表

 更新時(shí)間:2022年01月04日 11:33:23   作者:微小冷  
這篇文章主要介紹了C語言寫一個(gè)散列表,散列表,就是下標(biāo)可以為字母的數(shù)組。更多內(nèi)容和小編一起學(xué)習(xí)下面內(nèi)容吧

一、快速理解散列表

散列表,就是下標(biāo)可以為字母的數(shù)組。

假設(shè)現(xiàn)有一個(gè)數(shù)組int a[100],想查找其中第40個(gè)元素,則直接輸入a[40]就可以了,時(shí)間復(fù)雜度為O ( 1 ) O(1)O(1)。

問題在于,當(dāng)下標(biāo)不是數(shù)字,而是一個(gè)字符串的時(shí)候,可能需要一個(gè)超大的空間才能將所有下標(biāo)妥善地存放在特定的位置。例如,若以大小寫字母作為下標(biāo)索引,那么一位就需要預(yù)留52個(gè)空間,10位就需要52的10次方 這么大的空間,根本沒有設(shè)備可以滿足。

好在,52的10次方這么龐大的數(shù)字也超出了正常人的使用范圍,無論多長(zhǎng)的索引,我們能用上的值也絕對(duì)是有限的。

例如,現(xiàn)有下面三個(gè)字符串作為下標(biāo)

key1 = "microcold";
key2 = "tinycold";
key3 = "microcool";

其實(shí)只需要選取頭、尾兩個(gè)字母,就能很好地區(qū)分這三個(gè)字符串,即

def hash(key):
? ? return key[0]+key[-1]

但這種算法對(duì)索引字符的要求非常高,至少頭尾不能重復(fù)。所以,現(xiàn)在需要能把超長(zhǎng)字符串映射成特定短字符串而且盡量避免重復(fù)的算法。

二、散列函數(shù)

最簡(jiǎn)單的散列函數(shù)就是求余,將輸入字符串按位轉(zhuǎn)為整數(shù)之后求余。由于在字符串可能會(huì)轉(zhuǎn)成非常大的整數(shù),故需了解余數(shù)的性質(zhì)

(a+b)%c=(a%c+b %c)% c

相應(yīng)地有:

(a*b)%c=((a%c)*(b %c))% c

用C語言實(shí)現(xiàn)如下:

#include <stdio.h>
#define MAXHASH 100

//快速取冪法,a*b^n%c
int ?PowerMod (int a, int b, int n, int c)?
{ ?
? ? int ?ans = 1;?
? ? b = b % c;?
? ? while (n > 0) { ?
? ? ? ? if(n % 2 == 1)?
? ? ? ? ? ? ans = (ans * b) % c;?
? ? ? ? n = n / 2; ? ? ? //b >>= 1;
? ? ? ? b = (b * b) % c;?
? ? }?
? ? return (a*ans)%c;?
}?

int hash(char* key, int n){
? ? int addr = 0;
? ? for(int i = 0; i < n; i++){
? ? ? ? addr += PowerMod(key[i], 128, i, MAXHASH);
? ? }
? ? return addr%MAXHASH;
}

int main(){
? ? char* str;
? ? int i;
? ? while(1){
? ? ? ? gets(str);
? ? ? ? i = 0;
? ? ? ? while(str[i++]!='\0'){}
? ? ? ? printf("%d\n",hash(str,i));
? ? }
? ? return 0;
}

測(cè)試如下:

>gcc hash.c
>a.exe
asdf
21
microcold
81
tinycold
12
microcool
5
minicool
81
minicold
73

三、防撞

盡管minicool和microcold撞車了,但通過100以內(nèi)的位數(shù),去表示52的9次方 的樣本,也算是不錯(cuò)的表現(xiàn)了。

為了不發(fā)生撞車,則需更改數(shù)組中的元素類型——至少得是個(gè)結(jié)構(gòu)體。而防止撞車的方法很簡(jiǎn)單,如果發(fā)生撞車,那我就不散列了,直接發(fā)配到一個(gè)指定的數(shù)組中。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXHASH 100
typedef struct HASHNODE{
? ? char *key;
? ? int next;
} *hashNode;

struct HASHNODE* hashTable[MAXHASH];
struct HASHNODE* crashTable[MAXHASH]; ? ? //存儲(chǔ)撞擊之后的值
int numCrash=0; ? ? ? ? ? ? ? ? ? //已有的撞擊值

void initTable(){
? ? for(int i=0; i < MAXHASH; i++){
? ? ? ? hashTable[i] = (hashNode)malloc(sizeof(struct HASHNODE));
? ? ? ? hashTable[i]->key = NULL;
? ? ? ? hashTable[i]->next = -1;
? ? ? ? crashTable[i] = (hashNode)malloc(sizeof(struct HASHNODE));
? ? ? ? crashTable[i]->key = NULL;
? ? ? ? hashTable[i]->next = -1;
? ? }
}

void insertCrash(char* str, int index, int n){
? ? if(index == numCrash){
? ? ? ? crashTable[numCrash]->key = (char*)malloc(sizeof(char)*n);
? ? ? ? strcpy(crashTable[numCrash++]->key, str); ?//此時(shí)新增一個(gè)節(jié)點(diǎn)
? ? }
? ? else {
? ? ? ? if(crashTable[index]->next==-1)
? ? ? ? ? ? crashTable[index]->next = numCrash;
? ? ? ? insertCrash(str, hashTable[index]->next, n);
? ? }
}

//n為字符串長(zhǎng)度
void insertHash(char* str, int index,int n){
? ? if(hashTable[index]->key==NULL){
? ? ? ? hashTable[index]->key = (char*)malloc(sizeof(char)*n);
? ? ? ? strcpy(hashTable[index]->key, str);
? ? }else{
? ? ? ? if(hashTable[index]->next==-1)
? ? ? ? ? ? hashTable[index]->next = numCrash;
? ? ? ? insertCrash(str, hashTable[index]->next, n);
? ? }
}

void printHash(){
? ? for(int i = 0; i < MAXHASH; i++){
? ? ? ? if(hashTable[i]->key!=NULL)
? ? ? ? ? ? printf("hashTable[%d]:%s\n",i,hashTable[i]->key);
? ? ? ? if(crashTable[i]->key!=NULL)
? ? ? ? ? ? printf("crashTable[%d]:%s\n",i,crashTable[i]->key);
? ? }
}

int ?PowerMod (int a, int b, int n, int c)?
{ ?
? ? int ?ans = 1;?
? ? b = b % c;?
? ? while (n > 0) { ?
? ? ? ? if(n % 2 == 1)?
? ? ? ? ? ? ans = (ans * b) % c;?
? ? ? ? n = n / 2; ? ? ? //b >>= 1;
? ? ? ? b = (b * b) % c;?
? ? }?
? ? return (a*ans)%c;?
}?

int hash(char* key, int n){
? ? int addr = 0;
? ? for(int i = 0; i < n; i++){
? ? ? ? addr += PowerMod(key[i], 128, i, MAXHASH);
? ? }
? ? return addr%MAXHASH;
}

int main(){
? ? initTable();
? ? char* str;
? ? int i;
? ? while(1){
? ? ? ? gets(str);
? ? ? ? if(strcmp(str,"exit")==0) break;
? ? ? ? i = 0;
? ? ? ? while(str[i++]!='\0'){}
? ? ? ? insertHash(str,hash(str,i),i);
? ? ? ? printf("%d\n",hash(str,i));
? ? }
? ? printHash();
? ? return 0;
}

最后得到:

>gcc hash.c
>a.exe
asdf
21
hellworld
84
microcold
81
minicool
81
tinycool
20
tinycold
12
weixiaoleng
11
exit
crashTable[0]:minicool
hashTable[11]:weixiaoleng
hashTable[12]:tinycold
hashTable[20]:tinycool
hashTable[21]:asdf
hashTable[81]:microcold
hashTable[84]:hellworld

可見一方面的確散列了,另一方面也的確防撞了。

到此這篇關(guān)于C語言寫一個(gè)散列表的文章就介紹到這了,更多相關(guān)C語言寫散列表內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C++類和對(duì)象實(shí)戰(zhàn)之Date類的實(shí)現(xiàn)方法

    C++類和對(duì)象實(shí)戰(zhàn)之Date類的實(shí)現(xiàn)方法

    C++ 標(biāo)準(zhǔn)庫沒有提供所謂的日期類型,C++ 繼承了C語言用于日期和時(shí)間操作的結(jié)構(gòu)和函數(shù),這篇文章主要給大家介紹了C++類和對(duì)象實(shí)戰(zhàn)之Date類的實(shí)現(xiàn)方法,需要的朋友可以參考下
    2021-12-12
  • C++實(shí)現(xiàn)ETW進(jìn)行進(jìn)程變動(dòng)監(jiān)控詳解

    C++實(shí)現(xiàn)ETW進(jìn)行進(jìn)程變動(dòng)監(jiān)控詳解

    ETW提供了一種對(duì)用戶層應(yīng)用程序和內(nèi)核層驅(qū)動(dòng)創(chuàng)建的事件對(duì)象的跟蹤記錄機(jī)制。為開發(fā)者提供了一套快速、可靠、通用的一系列事件跟蹤特性。本文將利用ETW進(jìn)行進(jìn)程變動(dòng)監(jiān)控,需要的可以參考一下
    2022-07-07
  • Qt實(shí)現(xiàn)簡(jiǎn)單TCP服務(wù)器

    Qt實(shí)現(xiàn)簡(jiǎn)單TCP服務(wù)器

    這篇文章主要為大家詳細(xì)介紹了Qt實(shí)現(xiàn)簡(jiǎn)單TCP服務(wù)器,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-08-08
  • C++語言實(shí)現(xiàn)拼圖游戲詳解

    C++語言實(shí)現(xiàn)拼圖游戲詳解

    這篇文章主要為大家詳細(xì)介紹了C++基于EasyX庫實(shí)現(xiàn)拼圖小游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-09-09
  • 詳解C++虛函數(shù)表存儲(chǔ)位置

    詳解C++虛函數(shù)表存儲(chǔ)位置

    相信大家知道虛表指針和虛函數(shù)存儲(chǔ)的位置,但對(duì)于虛函數(shù)表的存儲(chǔ)位置一時(shí)無法確定。本文就來和大家詳細(xì)聊聊相關(guān)內(nèi)容,希望對(duì)大家有所幫助
    2023-04-04
  • C語言與C++內(nèi)存管理超詳細(xì)分析

    C語言與C++內(nèi)存管理超詳細(xì)分析

    C?語言內(nèi)存管理指對(duì)系統(tǒng)內(nèi)存的分配、創(chuàng)建、使用這一系列操作。在內(nèi)存管理中,由于是操作系統(tǒng)內(nèi)存,使用不當(dāng)會(huì)造成畢竟麻煩的結(jié)果。本文將從系統(tǒng)內(nèi)存的分配、創(chuàng)建出發(fā),并且使用例子來舉例說明內(nèi)存管理不當(dāng)會(huì)出現(xiàn)的情況及解決辦法
    2022-05-05
  • 使用devenv在命令行中編譯項(xiàng)目的方法

    使用devenv在命令行中編譯項(xiàng)目的方法

    下面小編就為大家分享一篇使用devenv在命令行中編譯項(xiàng)目的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2018-01-01
  • C語言數(shù)組應(yīng)用實(shí)現(xiàn)三子棋游戲

    C語言數(shù)組應(yīng)用實(shí)現(xiàn)三子棋游戲

    這篇文章主要為大家詳細(xì)介紹了C語言數(shù)組應(yīng)用實(shí)現(xiàn)三子棋游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-06-06
  • C語言中計(jì)算正弦的相關(guān)函數(shù)總結(jié)

    C語言中計(jì)算正弦的相關(guān)函數(shù)總結(jié)

    這篇文章主要介紹了C語言中計(jì)算正弦的相關(guān)函數(shù)總結(jié),包括正弦和雙曲線正弦以及反正弦的函數(shù),需要的朋友可以參考下
    2015-08-08
  • C++11非受限聯(lián)合體的使用

    C++11非受限聯(lián)合體的使用

    本文主要介紹了C++11非受限聯(lián)合體的使用,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-01-01

最新評(píng)論

娄底市| 屯昌县| 北川| 三河市| 辽源市| 奉化市| 金寨县| 永靖县| 洪江市| 南木林县| 高尔夫| 巴中市| 沧源| 沙坪坝区| 巴彦县| 荃湾区| 安乡县| 保定市| 叙永县| 邻水| 阿荣旗| 虹口区| 巫溪县| 宾阳县| 广西| 长汀县| 嫩江县| 杨浦区| 固安县| 辛集市| 邵武市| 六枝特区| 五家渠市| 法库县| 南京市| 故城县| 甘谷县| 贺州市| 麟游县| 尼木县| 都兰县|