1. 程式人生 > >雜湊表——拉鍊法

雜湊表——拉鍊法

一、Hash.h

#ifndef __HASH_H__
#define __HASH_H__

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

typedef int KeyType;

typedef struct HashNode
{
    KeyType _key;
    struct HashNode* _next;
}HashNode;

typedef struct HashTable
{
    HashNode** _tables; //指標陣列
    size_t _size;
    size_t _capacity;
}HashTable;

HashNode* BuyHashNode(KeyType key);
size_t HashFunc(HashTable* ht, KeyType key);
static
size_t GetNextPrimeNum(HashTable* ht); void HashTableInit(HashTable* ht, size_t Initsize); int HashTableInsert(HashTable* ht, KeyType key); HashNode* HashTableFind(HashTable* ht, KeyType key); int HashTableRemove(HashTable* ht, KeyType key); void HashTablePrint(HashTable* ht); void HashTableDestory(HashTable* ht); #endif __HASH_H__

二、Hash.cpp

#define _CRT_SECURE_NO_WARNINGS 1

#include "Hash.h"

//初始化
void HashTableInit(HashTable* ht, size_t Initsize)
{
    assert(ht);
    ht->_tables = (HashNode**)malloc(Initsize*sizeof(HashNode*));
    assert(ht->_tables);
    ht->_size = 0;
    ht->_capacity = Initsize;
    for
(size_t i = 0; i < ht->_capacity; i++) { ht->_tables[i] = NULL; } } //銷燬 void HashTableDestory(HashTable* ht) { assert(ht); for (size_t index = 0; index < ht->_capacity; index++) //先銷燬每一個連結串列 { HashNode* cur = ht->_tables[index]; while (cur) { HashNode* next = cur->_next; free(cur); cur = NULL; cur = next; } } free(ht->_tables); //再銷燬順序表 ht->_tables = NULL; ht->_size = ht->_capacity = 0; } //雜湊函式-查詢位置 size_t HashFunc(HashTable* ht, KeyType key) { return key % ht->_capacity; } //素數表 static size_t GetNextPrimeNum(HashTable* ht) { const int _PrimeSize = 28; static const unsigned long _PrimeList[_PrimeSize] = { 53ul, 97ul, 193ul, 389ul, 769ul, 1543ul, 3079ul, 6151ul, 12289ul, 24593ul, 49157ul, 98317ul, 196613ul, 393241ul, 786433ul, 1572869ul, 3145739ul, 6291469ul, 12582917ul, 25165843ul, 50331653ul, 100663319ul, 201326611ul, 402653189ul, 805306457ul, 1610612741ul, 3221225473ul, 4294967291ul }; int index = 0; while (index < _PrimeSize) { if (ht->_capacity < _PrimeList[index]) { return _PrimeList[index]; } index++; } return _PrimeList[_PrimeSize - 1]; } //擴容 void Checkcapacity(HashTable* ht) { assert(ht); if (ht->_size == ht->_capacity) //將載荷因子控制在1 { HashTable newht; //新建一個雜湊表 HashTableInit(&newht, GetNextPrimeNum(ht)); for (size_t i = 0; i < ht->_capacity; i++) { HashNode* cur = ht->_tables[i]; while (cur) { HashNode* next = cur->_next; //儲存下一個節點 size_t index = HashFunc(&newht, cur->_key); //重新計算原雜湊表中每一個key在新雜湊表中的位置 //利用原來已開闢的空間來進行連結,不用再重新開闢空間 cur->_next = newht._tables[index]; newht._tables[index] = cur; cur = next; } ht->_tables[i] = NULL; } free(ht->_tables); //銷燬原雜湊表 ht->_tables = newht._tables; //更新雜湊表 ht->_capacity = newht._capacity; } } //建立結點 HashNode* BuyHashNode(KeyType key) { HashNode* newnode = (HashNode*)malloc(sizeof(HashNode)); assert(newnode); newnode->_key = key; newnode->_next = NULL; return newnode; } //插入 int HashTableInsert(HashTable* ht, KeyType key) { assert(ht); Checkcapacity(ht); size_t index = HashFunc(ht, key); HashNode* cur = ht->_tables[index]; while (cur) { if (cur->_key == key) { return 0; } cur = cur->_next; } HashNode* newnode = BuyHashNode(key); newnode->_next = ht->_tables[index]; ht->_tables[index] = newnode; ht->_size++; return 1; } //查詢 HashNode* HashTableFind(HashTable* ht, KeyType key) { assert(ht); size_t index = HashFunc(ht, key); HashNode* cur = ht->_tables[index]; while (cur) { if (cur->_key == key) { return cur; } cur = cur->_next; } return NULL; } //刪除 int HashTableRemove(HashTable* ht, KeyType key) { assert(ht); size_t index = HashFunc(ht, key); HashNode* cur = ht->_tables[index]; if (cur == NULL) { return 0; } else if (cur->_next == NULL) { if (cur->_key == key) { free(cur); ht->_tables[index] = NULL; ht->_size--; return 1; } return 0; } else { HashNode* prev = ht->_tables[index]; while (cur) { if (cur->_key == key) { prev->_next = cur->_next; free(cur); cur = NULL; ht->_size--; return 1; } prev = cur; cur = cur->_next; } return 0; } } //列印 void HashTablePrint(HashTable* ht) { assert(ht); printf("\n"); for (size_t index = 0; index < ht->_capacity; index++) { HashNode* cur = ht->_tables[index]; while (cur) { printf("%d->", cur->_key); cur = cur->_next; } printf("NULL\n"); } printf("\n"); }

三、Test.cpp

#define _CRT_SECURE_NO_WARNINGS 1

#include "Hash.h"

int main()
{
    HashTable ht;
    HashTableInit(&ht, 5);
    int arr[] = { 10, 20, 30, 40, 50 };

    for (int i = 0; i < sizeof(arr) / sizeof(int); i++)
    {
        HashTableInsert(&ht, arr[i]);
    }
    HashTablePrint(&ht);

    HashNode* cur = HashTableFind(&ht, 1);
    if (cur)
    {
        printf("找到:%d\n", cur->_key);
    }
    else
    {
        printf("未找到\n");
    }

    HashTableInsert(&ht, 1);
    HashTableInsert(&ht, 2);
    HashTableInsert(&ht, 3);
    HashTableInsert(&ht, 4);
    HashTablePrint(&ht);

    cur = HashTableFind(&ht, 1);
    if (cur)
    {
        printf("找到:%d\n", cur->_key);
    }
    else
    {
        printf("未找到\n");
    }

    HashTableRemove(&ht, 1);
    HashTablePrint(&ht);

    cur = HashTableFind(&ht, 1);
    if (cur)
    {
        printf("找到:%d\n", cur->_key);
    }
    else
    {
        printf("未找到\n");
    }

    HashTableDestory(&ht);

    system("pause");
    return 0;
}