zoukankan      html  css  js  c++  java
  • 散列表

    散列表

      散列表的实现叫做散列。散列是一种以常数时间执行插入、删除和查找的技术。理想的散列数据结构只不过是一个包含有关键字的具有固定大小的数组。每个关键字带有一个或多个相关的值,并且每个关键字通过一个映射函数映射到散列表的适当的单元中。散列函数可以选择Horner函数:KeySize1i=0Key(KeySizei1)32i。解决当插入一个元素时,该处已经存在另一个元素时的冲突问题的简单方法有:分离链接法和开放定址法。

      分离链接法是将散列到同一个值的所有元素保留到一个表中。

    /*
     *分离链接法散列表
     */
    
    #ifndef SP_HASH_TABLE_H
    #define SP_HASH_TABLE_H
    
    #include <stdlib.h>
    #include <string.h>
    #include <assert.h>
    
    /*散列表值类型*/
    typedef int ElementType;
    
    typedef struct SPHashValue
    {
        ElementType hash_value;
        char hash_key[8];
        struct SPHashValue *next;
    } SPHashValue;
    
    /*散列表数据结构*/
    typedef struct SPHashTable 
    {
        int table_size; //散列表大小
        SPHashValue **hash_value_ptr; //指向散列值链表的指针
    } SPHashTable;
    
    
    
    /*给散列表链表节点分配内存*/
    SPHashValue* create_note(const char *key, ElementType hash_value)
    {
        SPHashValue *node = (SPHashValue*)malloc(sizeof(SPHashValue));
        if (node == NULL)
          return NULL;
        node->hash_value = hash_value;
        strncpy(node->hash_key, key, 7);
        node->hash_key[7] = '';
        node->next = NULL;
        return node;
    }
    
    /*释放散列表散列值链表内存*/
    void free_hash_value(SPHashValue *hash_value_list)
    {
        SPHashValue *tmp = NULL;
        while (hash_value_list)
        {
            tmp = hash_value_list->next;
            free(hash_value_list);
            hash_value_list = tmp;
        }
    }
    
    /*创建散列表,并初始化*/
    SPHashTable* create_hash_table(int size)
    {
        SPHashTable* hash_table = (SPHashTable*)malloc(sizeof(SPHashTable));
        hash_table->table_size = size;
        hash_table->hash_value_ptr = (SPHashValue**)malloc(sizeof(SPHashValue) * size);
    
        for (int i = 0; i < size; ++i)
        {
            hash_table->hash_value_ptr[i] = NULL; 
        }
        return hash_table;
    }
    
    /*删除散列表*/
    void delete_hash_table(SPHashTable *hash_table)
    {
        SPHashValue *tmp = NULL;
        /*释放散列值链表*/
        for (int i = 0; i < hash_table->table_size; ++i)
        {
            free_hash_value(hash_table->hash_value_ptr[i]);
        }
       /*释放指向散列值链表的指针的内存*/
        free(hash_table->hash_value_ptr);
    
        free(hash_table);
    
    }
    
    /*散列函数*/
    int horner_hash(const char *key, int table_size)
    {
        int hash_value = 0;
    
        while (*key != '')
        {
            hash_value = (hash_value * 27) + *key++;
        }
    
        return hash_value % table_size;
    }
    
    /*添加元素到散列表*/
    void add(const SPHashTable *hash_table, const char *key, const ElementType value)
    {
       int hash_value = horner_hash(key, hash_table->table_size);
       SPHashValue *value_note = create_note(key, value);
       assert(value_note != NULL);
       SPHashValue *tmp = hash_table->hash_value_ptr[hash_value];
       if (tmp == NULL)
       {
         hash_table->hash_value_ptr[hash_value] = value_note;
         return;
       }
       while (tmp->next != NULL)
       {
            tmp = tmp->next;
       }
       tmp->next = value_note;
    
    }
    
    /*在散列表中查找键,返回其在散列表中的位置*/
    SPHashValue* find(const SPHashTable *hash_table, const char *key)
    {
        int hash_value =  horner_hash(key, hash_table->table_size);
        SPHashValue *tmp = hash_table->hash_value_ptr[hash_value];
        while (tmp)
        {
            if (strcmp(tmp->hash_key, key) == 0)
              return tmp;
            tmp = tmp->next;
        }
    
        return NULL;
    }
    
    /*删除散列表中的指定的键值,删除成功返回1,后则返回0*/
    int delete_keyvalue(const SPHashTable *hash_table, const char *key)
    {
        int hash_value = horner_hash(key, hash_table->table_size);
        SPHashValue *tmp_prev = hash_table->hash_value_ptr[hash_value];
        if (tmp_prev == NULL)
          return 0;
    
        if (strcmp(tmp_prev->hash_key, key) == 0) //待删除键值链表第一个元素
        {
            free(tmp_prev);
            hash_table->hash_value_ptr[hash_value] = NULL;
            return 1;
        }
        SPHashValue *tmp = tmp_prev->next;
        while (tmp)
        {
            if (strcmp(tmp->hash_key, key) == 0)
            {
                tmp_prev->next = tmp->next;
                free(tmp);
                return 1;
            }
            tmp_prev = tmp;
            tmp = tmp->next;
        }
    
        return 0;
    }
    
    #endif /*end sp_hash_table.h*/

      开放定地址散列法中,如果有冲突发生,那么就尝试选择另外的单元,直到找出空的单元为止。常常选择一个冲突解决函数F(i)来解决表的散列,散列函数hi(X)=(Hash(X)+F(i))modTableSize

  • 相关阅读:
    python chunk 方式读取大文件——本质上还是file read自身支持
    将tflearn的模型保存为pb,给TensorFlow使用
    将TensorFlow模型变为pb——官方本身提供API,直接调用即可
    Ubuntu17.10 下配置caffe 仅CPU i386可以直接apt install caffe-cpu,但是怎么运行mnist代码我懵逼了
    tflearn中计算混淆矩阵方法——需要经过一步转换
    词袋模型 测试数据使用和训练数据一样的词汇表
    借贷宝“自我绑架”:传销式推广只能“烧钱”玩下去?
    借贷宝被看衰 九鼎投资真正意图是什么?
    借贷宝注册送现金疯转 新闻PS图背后真相
    拜读了《婆媳关系好坏取决于老公》一文,看似有道理,细读感觉其实应该不是那么回事
  • 原文地址:https://www.cnblogs.com/corfox/p/5414999.html
Copyright © 2011-2022 走看看