散列表

散列表

  散列表的实现叫做散列。散列是一种以常数时间执行插入、删除和查找的技术。理想的散列数据结构只不过是一个包含有关键字的具有固定大小的数组。每个关键字带有一个或多个相关的值,并且每个关键字通过一个映射函数映射到散列表的适当的单元中。散列函数可以选择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] = '\0';
    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 != '\0')
    {
        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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值