• C语言 实现 HashTable


    #include <stdlib.h>
    #include <string.h>
    #include <stdio.h>
    /**----------------------------------------哈希表节点-----------------------------------**/
    typedef struct _Node {
        void * key;
        void * value;
        int  hash;
        struct _Node * next;
    } Node;
    /**----------------------------------------哈希表节点结束-------------------------------**/
    /**-------------------------------------------------------------------------------------**/
    /**-------------------------------------------------------------------------------------**/
    /**-------------------------------------------------------------------------------------**/
    /**----------------------------------------哈希表---------------------------------------**/
    typedef  struct _HashTable {
        int cnt;
        int tableLength;
        Node ** tables;
        // simple Methord
        void (*put)(struct _HashTable *this, const void *key, void* value);
        void*(*get)(struct _HashTable *this, const void *key);
        void (*destroy)(struct _HashTable *this);
        void (*resize)(struct _HashTable *this);
        // help Methord 需要声明
        Node* (*Create_Node)(const void * key, void* value, int hash);
        void  (*Destory_Node)(Node * node);
        int   (*Compute_Hash)(const void * key);
        int   (*Keys_Equal)(const void * s, const void * t);
    } HashTable;
    
    void put(HashTable *this, const void *key, void * value) {
        int hash = this -> Compute_Hash(key);
        int pos  = hash & (this -> tableLength - 1);
        Node * head = this -> tables[pos];
        while(head != NULL) {
            if (this -> Keys_Equal(key, head -> key) == 0) {
                head -> value = value;
                return;
            }
            head = head -> next;
        }
        if (this -> cnt  >= (int)(this -> tableLength * 0.75)) {
            this -> resize(this);
            pos  = hash & (this -> tableLength - 1);
        }
        this -> cnt = this -> cnt + 1;
        Node * in = this -> Create_Node(key, value, hash);
        in -> next  = this -> tables[pos];
        this -> tables[pos] = in;
    }
    
    void* get(HashTable *this, const void *key) {
        int hash = this -> Compute_Hash(key);
        int pos  = hash & (this -> tableLength - 1);
        Node * head = this -> tables[pos];
        while(head != NULL) {
            if (this -> Keys_Equal(key, head -> key) == 0) {
                return head -> value;
            }
            head = head -> next;
        }
        return NULL;
    }
    void resize(HashTable *this) {
        int tableLength  =  this -> tableLength << 1;
        int i;
        Node * tmp;
        Node ** tables = (Node **)malloc(sizeof(Node *) * tableLength);
        memset(tables, 0, sizeof(Node *) * tableLength);
    
        // 拷贝 速度
        for(i = 0; i < this -> tableLength; ++i) {
            Node * head = this -> tables[i];
            while(head != NULL) {
                tmp = head;
                head = head -> next;
                int pos =  tmp -> hash & (tableLength - 1 );
                tmp -> next = tables[pos];
                tables[pos] = tmp;
            }
        }
        // 防止被别人申请到 但是不是0,其实不操作也没事
        memset(this -> tables, 0, sizeof(Node *) * this -> tableLength);
        free(this -> tables);
        this -> tables = tables;
        this -> tableLength = tableLength;
    }
    // 最后写 这是 C/C++ 语言最恶心的地方,切记
    void destroy(HashTable *this) {
        int i = this -> tableLength;
        Node * next;
        for(i = 0; i < this -> tableLength; ++i) {
            Node * now  = this -> tables[i];
            while(now != NULL) {
                next = now -> next;
                this -> Destory_Node(now);
                now = next;
            }
        }
        free(this -> tables);
    }
    
    /**
     * @param Create_Node   创建hash节点的函数
     * @param Compute_Hash  计算hash节点key 的hashCode 的函数
     * @param Keys_Equal    判断hash节点key 相等的函数,判断  == 0 代表相等
     * @param Destory_Node  销毁hash节点的函数:
     * Description: 初始化 hash表
     *  之所以 需要填写 这么多的函数,主要是因为,HashNode 的key, value  在是指针的情况下,需要确定
     *      (1):初始化Node: 是拷贝模式,还是 直接使用模式
     *      (2):销毁  Node: 是否需要 去 free 掉
     *  所以 需要 手动的传递这么多函数
     *  一个 字符串作为 key
     */
    HashTable * initTable(Node* (*Create_Node)(const void * key, void * value, int hash),
                        int (*Compute_Hash)(const void * key),
                        int (*Keys_Equal)(const void *s, const void *t),
                        void (*Destory_Node)(Node * node)) {
        HashTable * ans = (HashTable*)malloc(sizeof(HashTable));
        ans -> cnt = 0 ;
        ans -> tableLength = 8;
        ans -> put = put;
        ans -> get = get;
        ans -> destroy = destroy;
        ans -> resize  = resize;
        ans -> Create_Node  = Create_Node;
        ans -> Compute_Hash = Compute_Hash;
        ans -> Keys_Equal   = Keys_Equal;
        ans -> Destory_Node = Destory_Node;
        Node ** tables = (Node **)malloc(sizeof(Node *) * ans -> tableLength);
        memset(tables, 0, sizeof(Node *) * ans -> tableLength);
        ans -> tables = tables;
        return ans;
    }
    
    
    /**----------------------------------------哈希表结束---------------------------------------**/
    
    /*
        下面三个函数,主要实现
            key(type = "字符串", mode = "拷贝模式")
            value(type = "int", mode = "拷贝模式")
    */
    Node * initNode(const void * _key, void * _value, int hash){
        Node * in   = (Node *)malloc(sizeof(Node));
    
        char * key  = (char *)_key;
        int kLen    = strlen(key);
        char * copy = (char *)malloc(sizeof(char) * (kLen + 1));
        strcpy(copy, key);
        in -> key   = (void *) copy;
    
        int * value = (int *)malloc(sizeof(int));
        *value = *((int*)_value);
        in -> value = value;
    
        in -> hash  = hash;
        in -> next  = NULL;
        return in;
    }
    void destoryNode(Node * node) {
        free(node -> key);
        free(node -> value);
        node -> key = node -> next = node -> value = NULL;
        free(node);
    }
    int String_Hash_Code(const void * _ch) {
        const char * ch = (const char *)_ch;
        int i = 0, ans = 0;
        for(i = 0 ; ch[i] != ''; ++i) {
            ans = 31 * ans + ch[i];
        }
        return ans;
    }
    
    int stringEqual(const void * _s, const void * _t) {
        return strcmp(_s, _t);
    }
    
    int main() {
        HashTable* table = initTable(initNode, String_Hash_Code, stringEqual, destoryNode);
        char a[20];
        int  value, n;
        scanf("%d", &n);
        for(int w = 0; w < n; ++w) {
            scanf("%s %d", a, &value);
            table -> put(table, a, &value);
        }
        printf("table size %d, length %d
    ", table -> cnt, table -> tableLength);
        printf("%s, %d
    ", "1221",  *(int*)table -> get(table, "1221"));
        int* ans = (int*)table -> get(table, "12312");
        printf("%s, %d
    ", "12312", ans == NULL ? -1 : *ans);
        table -> destroy(table);
        free(table);
        return 0;
    }
  • 相关阅读:
    visual studio 目录
    CMake教程小结
    CMake教程
    blender坐标系梳理
    Blender3d obj坐标转换示意图
    行列式的向量形式
    高等代数 第一章 行列式
    C++ Union实验
    git 分支合并学习实验
    C++使用memset注意事项
  • 原文地址:https://www.cnblogs.com/shuly/p/12198455.html
Copyright © 2020-2023  润新知