c語言實現哈希表數據結構


哈希表的數據結構:

其實就是數組+鏈表:如圖,

 

 

     通過一個hash函數將key轉化成數組的下標,如果對應的下標在數組里面有數據,那么就沖突了,沖突了怎么辦呢,這個時候就把這個數組當成鏈表的頭結點,然后通過頭插法或者尾插法將新的節點數據插入到這個鏈表里面,理論上有hash表的size有多大,就有多少條鏈表,上圖就有16條,沖突得越多,鏈表的長度就越大。由於查找key的時候,通過key算出對應的數組下標,這個計算的過程是hash算法實現的,一般時間復雜度為O(1),所以得到下標的時間復雜度是O(1), 通過下標在數組中找數據的時間復雜度也是O(1), 所以哈希表的查找的時間復雜度在沒有沖突的情況下是O(1), 一旦有沖突,那么就要遍歷鏈表了。這個時候的時間復雜度就是根據鏈表的長度來決定的。

       通過上面的數據結構,能夠定義出每個hash節點的數據結構

typedef struct HashNode{
    char *key;                 
    int value;
    struct HashNode *nextNode;
}HashNode;

      而哈希表即上面HashNode的數組

typedef struct HashTable{
    HashNode * hashNode[MAX_TABLE_SIZE];
    int currentIndex;
}HashTable;

  好了,我們的數據結構構造出來了之后,接下來就是,初始化,添加,查找,刪除,等一系列操作hash表的騷操作了

  


 

 初始化:

void InitHashTable(HashTable *hashTable)
{
    memset(hashTable->hashNode, 0, sizeof(HashNode *) * MAX_TABLE_SIZE);
    hashTable->currentIndex = 0;
}

 


插入函數:

//插入key value
void Insert(HashTable *hashTable, char *key, int value)
{
    int pos = HashFun(key) % MAX_TABLE_SIZE;
    HashNode * newNode = (HashNode *)malloc(sizeof(HashNode));
    newNode->nextNode = NULL;
    newNode->key = (char *)malloc(sizeof(char) * (strlen(key) + 1));
    strcpy(newNode->key, key);
    newNode->key[strlen(key)] = '\0';
    newNode->value = value;
    HashNode *p = hashTable->hashNode[pos];
    if (p == NULL) {  //如果頭結點為空,說明沒有沖突
        hashTable->hashNode[pos] = newNode;
        hashTable->currentIndex++;
        return;
    }
    //頭結點不為空,同時頭結點的key和輸入的key相同,覆蓋value
    if (strcmp(p->key, key) == 0) {
        p->value = value;
        return;
    }

    //頭結點不為空,沖突,插入到鏈表的第二個節點
    HashNode *q = p->nextNode;
    newNode->nextNode = q;
    p->nextNode = newNode;
}

 


 

獲取key對應的value

int * Get(HashTable *hashTable, char *key)
{
    int pos = HashFun(key) % MAX_TABLE_SIZE;
    HashNode *p = hashTable->hashNode[pos];
    if (p == NULL) {  //如果頭結點為空,說明不存在這樣的key
        return NULL;
    } else {
        HashNode *q = p;
        while (q != NULL) {
            if(strcmp(q->key, key) == 0) {
                return &(q->value);
            }
            q = q->nextNode;
        }
        return NULL;
    }
}

 


 

刪除對應的key

int Drop(HashTable *hashTable, char *key)
{
    int pos = HashFun(key) % MAX_TABLE_SIZE;
    HashNode *p = hashTable->hashNode[pos];
    if (p == NULL) {  //如果頭結點為空,說明不存在這樣的key
        return 0;
    }
    else {
        if(strcmp(p->key, key) == 0) {  //刪除的如果是頭結點
            hashTable->hashNode[pos] = p->nextNode;
            free(p->key);
            free(p);
            return 1;
        }
        //刪除的不是頭結點的情況
        HashNode *q = p->nextNode;
        HashNode * last = p;
        while (q != NULL) {
            if(strcmp(q->key, key) == 0) {
                last->nextNode = q->nextNode;
                free(q->key);
                free(q);
                return 1;
            }
            last = q;
            q = q->nextNode;
        }
        return 0;
    }
}

 


 

打印所有數據

void PrintHashTable(HashTable *hashTable)
{
    for(int i = 0; i < MAX_TABLE_SIZE; i++) {
        HashNode *head = hashTable->hashNode[i];
        if (head == NULL)
            continue;
        printf("\n數組下標:%d======>", i);
        printf("(%s:%d)", head->key, head->value);
        head = head->nextNode;
        while(head) {
            printf("-->(%s:%d)", head->key, head->value);
            head = head->nextNode;
        }
    }
}

 


 

釋放堆內存

void ClearHashTable(HashTable* hashTable)
{
    for(int i = 0; i < MAX_TABLE_SIZE; i++) {
        HashNode *head = hashTable->hashNode[i];
        while(head) {
            HashNode *temp = head->nextNode;
            free(head->key);
            free(head);
            head = temp;
        }
    }
}

 


 

哈希規則

unsigned long HashFun(const char *key)
{
    unsigned long hash = 0;
    int len = strlen(key);
    for (int i = 0; i < len; i++) {
        hash = hash * 33 + key[i];
    }
    return hash;
}

 


 

main函數測試

int main(void)
{
    HashTable *hashTable = (HashTable *)malloc(sizeof(HashTable));
    InitHashTable(hashTable);
    Insert(hashTable,"1234", 1);
    Insert(hashTable,"11234", 1);
    Insert(hashTable,"hello", 2);
    Insert(hashTable,"world", 3);
    Insert(hashTable,"hzp", 4);
    Insert(hashTable,"java", 5);
    Insert(hashTable,"b", 12);
    Insert(hashTable,"c", 12);
    Insert(hashTable,"c1", 12);
    Insert(hashTable,"c++", 18);
    Insert(hashTable,"html", 18);
    Insert(hashTable,"web", 18);
    Insert(hashTable,"python", 56);
    PrintHashTable(hashTable);
    int *data = Get(hashTable,"b");
    printf("\n====%d=====\n", *data);
    Drop(hashTable, "python");
    PrintHashTable(hashTable);
    ClearHashTable(hashTable);

}

運行截圖:

 

 附代碼:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAX_KEY_LEN 100
#define MAX_TABLE_SIZE 1000

typedef struct HashNode{
    char *key;
    int value;
    struct HashNode *nextNode;
}HashNode;


typedef struct HashTable{
    HashNode * hashNode[MAX_TABLE_SIZE];
    int currentIndex;
}HashTable;


unsigned long HashFun(const char *key)
{
    unsigned long hash = 0;
    int len = strlen(key);
    for (int i = 0; i < len; i++) {
        hash = hash * 33 + key[i];
    }
    return hash;
}
//初始化
void InitHashTable(HashTable *hashTable)
{
    memset(hashTable->hashNode, 0, sizeof(HashNode *) * MAX_TABLE_SIZE);
    hashTable->currentIndex = 0;
}

//插入key value
void Insert(HashTable *hashTable, char *key, int value)
{
    int pos = HashFun(key) % MAX_TABLE_SIZE;
    HashNode * newNode = (HashNode *)malloc(sizeof(HashNode));
    newNode->nextNode = NULL;
    newNode->key = (char *)malloc(sizeof(char) * (strlen(key) + 1));
    strcpy(newNode->key, key);
    newNode->key[strlen(key)] = '\0';
    newNode->value = value;
    HashNode *p = hashTable->hashNode[pos];
    if (p == NULL) {  //如果頭結點為空,說明沒有沖突
        hashTable->hashNode[pos] = newNode;
        hashTable->currentIndex++;
        return;
    }
    //頭結點不為空,同時頭結點的key和輸入的key相同,覆蓋value
    if (strcmp(p->key, key) == 0) {
        p->value = value;
        return;
    }

    //頭結點不為空,沖突,插入到鏈表的第二個節點
    HashNode *q = p->nextNode;
    newNode->nextNode = q;
    p->nextNode = newNode;
}

int * Get(HashTable *hashTable, char *key)
{
    int pos = HashFun(key) % MAX_TABLE_SIZE;
    HashNode *p = hashTable->hashNode[pos];
    if (p == NULL) {  //如果頭結點為空,說明不存在這樣的key
        return NULL;
    } else {
        HashNode *q = p;
        while (q != NULL) {
            if(strcmp(q->key, key) == 0) {
                return &(q->value);
            }
            q = q->nextNode;
        }
        return NULL;
    }
}

int Drop(HashTable *hashTable, char *key)
{
    int pos = HashFun(key) % MAX_TABLE_SIZE;
    HashNode *p = hashTable->hashNode[pos];
    if (p == NULL) {  //如果頭結點為空,說明不存在這樣的key
        return 0;
    }
    else {
        if(strcmp(p->key, key) == 0) {  //刪除的如果是頭結點
            hashTable->hashNode[pos] = p->nextNode;
            free(p->key);
            free(p);
            return 1;
        }
        //刪除的不是頭結點的情況
        HashNode *q = p->nextNode;
        HashNode * last = p;
        while (q != NULL) {
            if(strcmp(q->key, key) == 0) {
                last->nextNode = q->nextNode;
                free(q->key);
                free(q);
                return 1;
            }
            last = q;
            q = q->nextNode;
        }
        return 0;
    }
}


void ClearHashTable(HashTable* hashTable)
{
    for(int i = 0; i < MAX_TABLE_SIZE; i++) {
        HashNode *head = hashTable->hashNode[i];
        while(head) {
            HashNode *temp = head->nextNode;
            free(head->key);
            free(head);
            head = temp;
        }
    }
}

void PrintHashTable(HashTable *hashTable)
{
    for(int i = 0; i < MAX_TABLE_SIZE; i++) {
        HashNode *head = hashTable->hashNode[i];
        if (head == NULL)
            continue;
        printf("\nindex:%d======>", i);
        printf("(%s:%d)", head->key, head->value);
        head = head->nextNode;
        while(head) {
            printf("-->(%s:%d)", head->key, head->value);
            head = head->nextNode;
        }
    }
}

int main(void)
{
    HashTable *hashTable = (HashTable *)malloc(sizeof(HashTable));
    InitHashTable(hashTable);
    Insert(hashTable,"1234", 1);
    Insert(hashTable,"11234", 1);
    Insert(hashTable,"hello", 2);
    Insert(hashTable,"world", 3);
    Insert(hashTable,"hzp", 4);
    Insert(hashTable,"java", 5);
    Insert(hashTable,"b", 12);
    Insert(hashTable,"c", 12);
    Insert(hashTable,"c1", 12);
    Insert(hashTable,"c++", 18);
    Insert(hashTable,"html", 18);
    Insert(hashTable,"web", 18);
    Insert(hashTable,"python", 56);
    PrintHashTable(hashTable);
    int *data = Get(hashTable,"b");
    printf("\n====%d=====\n", *data);
    Drop(hashTable, "python");
    PrintHashTable(hashTable);
    ClearHashTable(hashTable);

}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM