zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    稳扎稳打Silverlight(13) 2.0交互之鼠标事件和键盘事件
    稳扎稳打Silverlight(17) 2.0数据之详解DataGrid, 绑定数据到ListBox
    再接再厉VS 2008 sp1 + .NET 3.5 sp1(2) Entity Framework(实体框架)之详解 Linq To Entities 之一
    稳扎稳打Silverlight(8) 2.0图形之基类System.Windows.Shapes.Shape
    稳扎稳打Silverlight(11) 2.0动画之ColorAnimation, DoubleAnimation, PointAnimation, 内插关键帧动画
    稳扎稳打Silverlight(21) 2.0通信之WebRequest和WebResponse, 对指定的URI发出请求以及接收响应
    稳扎稳打Silverlight(16) 2.0数据之独立存储(Isolated Storage)
    稳扎稳打Silverlight(9) 2.0画笔之SolidColorBrush, ImageBrush, VideoBrush, LinearGradientBrush, RadialGradientBrush
    稳扎稳打Silverlight(23) 2.0通信之调用WCF的双向通信(Duplex Service)
    游戏人生Silverlight(1) 七彩俄罗斯方块[Silverlight 2.0(c#)]
  • 原文地址:https://www.cnblogs.com/shuly/p/12198455.html
Copyright © 2011-2022 走看看