所谓的哈希表-散列方法

所谓的哈希表-散列方法就是一个结构体数组,一般的数组下表是012345,要找数据只能通过遍历;
    哈希的数组也是012345,但是这个下标号是通过key值换算得来的(这个映射函数叫做散列函数,存放记录的数组叫做散列表。)。
   通过key值换算成数组下标号,不需要遍历,直接找到数据;

下面是网上的一个c语言实现,比较简单,容易理解。

#ifndef _HASH_TABLE_H
#define _HASH_TABLE_H
#include <stdlib.h>
#include <memory.h>
#include <stdio.h>
#include <string.h>
#define HASH_TABLE_CAPACITY 20

typedef unsigned int uint;

/** hash table element*/
typedef struct _htItem{
    struct _htItem  *next;// 指向下一个的指针
    char *key_string;// key
    uint fid;// 记录值

} htItem;

/** init the hashTable 构造函数,申请哈希表的空间*/
void htInit(htItem **ht, uint length);

/** set hashTable element 哈希表中插入一个值*/
uint htSet(char *key, uint val, htItem **ht);

/** get element from hashtable 从哈希表中获得一个对应的key*/
htItem* htGet(char *key, htItem **ht);

/** Delete element from hashTable 从哈希表中删除一个key*/
int htDel(char *key, htItem **ht);

/** BKDR hash function 对string进行散列得到一个整数值*/
uint bkdrHash(char *key);

/** get the index of hash table 根据key计算一个整数值,然后获得对应的槽位*/
uint htIndex(char *key, htItem **ht);

/** get hashTable elements */
uint htLen(htItem **ht);

/*打印哈希表*/
void print_hashTable(htItem **ht);
#endif

 

#include <stdlib.h>
#include <stdio.h>
#include "hash.h"

/**************************************************************************************************
**	哈希表的类型是对一个string进行散列。
**	本哈希表使用的是开散列的办法,首先是一个指针数组,数组第一个位置中保存着哈希表的大小。
**	首先对string散列获得一个整数值,然后根据哈希表的大小计算所属的槽位,
**	然后再该槽位的链表上进行查找,如果找到则更新哈希值,如果未找到则在尾端插入。
**************************************************************************************************/

/*初始化HashTable*/
void htInit(htItem **ht, uint length){
    int i;
    for (i = 0; i<length; i++){
        ht[i] = (htItem*)malloc(sizeof(htItem));
        memset(ht[i], 0, sizeof(htItem));
    }
    ht[0]->fid = length;/*数组第一个位置中保存着哈希表的大小*/
}

/** get hashTable elements 进行对应的hash值的搜索,如果找到则返回该节点*/
htItem* htGet(char *key, htItem **ht){
    uint i = htIndex(key, ht);
    htItem *item = ht[i]->next;
    htItem *tmp = (htItem*)malloc(sizeof(htItem));
    memset(tmp, 0, sizeof(htItem));
	printf("htGet key = %s, index = %d\n",key,i);
    while (item)
    {
        if (strcmp(key, item->key_string) == 0){
            return item;
        }
        item = item->next;
    }
    return NULL;
}


/** set hashTable element 插入新的hash值*/
uint htSet(char *key, uint fid, htItem **ht){
    uint i = htIndex(key, ht);
    htItem *item = ht[i];
	printf("htSet key = %s, index = %d\n",key,i);
    while (item->next)
    {
		/*已经存在的话则直接更新值*/
        if (strcmp(key, item->next->key_string) == 0){
            item->next->fid = fid;
            return 0;
        }
        else{
            item = item->next;
        }
    }
    item->next = (htItem*)malloc(sizeof(htItem));
    item->next->fid = fid;
    item->next->key_string = key;
    item->next->next = NULL;
    return 0;
}

/** delete one element of hashtable  删除hash值*/
int htDel(char *key, htItem **ht){
    uint i = htIndex(key, ht);
    htItem *item = ht[i];
	printf("htDel key = %s, index = %d\n",key,i);
    while (item->next){
        if (strcmp(key, item->next->key_string) == 0){
            htItem *tmp = item->next;
            item->next = tmp->next;
            free(tmp);
            return 0;
        }
        item = item->next;
    }
    return -1;
}

/** BKDR hash function  对字符串进行散列,得到一个整数的hash值*/
uint bkdrHash(char *key)
{
    uint seed = 131;
    uint hash = 0;
	int iRet = 0;
    while (*key != '\n' && *key != 0)
    {
        hash = hash * seed + (*key++);
		printf("bkdrHash:while key %s,tmp hash %d\n",key,hash);
    }
	iRet = (hash & 0x7FFFFFFF);
	printf("bkdrHash:key %s,hash %d,iRet %d\n",key,hash,iRet);
    return iRet;
}
/** get the index of hash table  根据得到的hash值选择一个槽位置*/
uint htIndex(char *key, htItem **ht){
	int iRet = 0;
    uint hashedKey = bkdrHash(key);
    uint length = (ht[0]->fid - 1);
	iRet = (uint)hashedKey % length + 1;
	printf("htIndex:key %s,iRet %d\n",key,iRet);
    return iRet;
}

/** get element number in the hashtable */
uint htLen(htItem **ht){
    uint alength = ht[0]->fid;
    uint i, length = 0;
    for (i = 1; i < alength; i++){
        if (ht[i]->next) {
            length++;
        }
    }
    return length;
}

/** get capacity of hashtable */
uint htCapacity(htItem **ht)
{
    return ht[0]->fid;
}

void print_hashTable(htItem **ht)
{
    uint length = ht[0]->fid;
    uint i;
    htItem *item;
	
	printf("\n============ Printf all table =============\n");
	
    for (i = 1; i < length; i++)
    {
        item = ht[i]->next;
        while (item)
        {
            printf("all %s => fid = %d, index = %d\n", item->key_string, item->fid, i);
            item = item->next;
        }
    }
	printf("================= End ==================\n\n");
}



int main()
{
    htItem *item[101];
    htInit(item, 101);

    htSet("aaa", 100, item);
    htSet("bbb", 1000, item);
    htSet("ccc", 99, item);
    htSet("ddd1", 199, item);
    htSet("ddd2", 299, item);
    htSet("ddd3", 399, item);
    htSet("ddd4", 499, item);
    htSet("ddd5", 599, item);
    htSet("ddd6", 699, item);
    htSet("ddd7", 799, item);
    htSet("ddd8", 899, item);
    htSet("ddd9", 999, item);
    htSet("ddd10", 1099, item);
    htSet("ddd11", 1199, item);
    htSet("ddd12", 1299, item);
    htSet("ddd13", 1399, item);

	print_hashTable(item);

    htItem *tmp = htGet("aaa", item);
    htItem *tmp1 = htGet("bbb", item);
    htItem *tmp2 = htGet("ccc", item);
	printf("\nGeting aaa,bbb,ccc...\n");
	printf("tmp1: Key %s => %d\n", tmp->key_string, tmp->fid);
    printf("tmp2: Key %s => %d\n", tmp1->key_string, tmp1->fid);
    printf("tmp3: Key %s => %d\n", tmp2->key_string, tmp2->fid);

    printf("\nDelete bbb ...\n");
    htDel("bbb", item);


    print_hashTable(item);

    htItem *tmp3 = htGet("bbb", item);

    printf("tmp3 pointer:%u\n", tmp3);

    if (tmp3) {
        printf("Key %s => %d\n", tmp3->key_string, tmp3->fid);
    }
}




 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 在散列表中,同义词是指具有相同散列地址的两个元素。这种情况也被称为哈希冲突。为了解决哈希冲突,通常会采用开放地址法或链式地址法。开放地址法是指在散列表中寻找下一个可用的空槽位来存储冲突的元素,而链式地址法则是将冲突的元素存储在同一个散列地址下的链表中。 ### 回答2: 散列表是一种常见的数据结构,它通过散列函数将元素映射到散列地址,以实现快速的查找、插入和删除操作。然而,由于不同的元素可能会映射到同一个散列地址上,散列表中就会出现所谓的同义词。 同义词指的是具有相同散列地址的两个元素。当这两个元素被插入到同一个散列地址上时,就形成了冲突,通常需要通过解决冲突的方法来处理它们。 解决冲突的方法有很多种,其中比较常见的方法包括开放寻址法和链式法。开放寻址法是指当一个元素的散列地址被占用时,继续在散列表中寻找下一个空闲的位置来插入它;而链式法则是利用链表或者其他数据结构来将具有相同散列地址的元素组织起来。 在实际应用中,同义词的出现无法避免,但是通过合适的解决冲突方法可以使散列表的性能得到优化,提高算法的效率。当然,为了避免大量的冲突,我们也可以通过优化散列函数来减少散列冲突的发生。 总之,同义词在散列表中是一种常见的现象,需要通过适当的解决冲突方法来处理。在实际应用中,我们需要根据具体情况来选择合适的解决冲突方法,并且通过不断地优化来提高算法的效率和稳定性。 ### 回答3: 散列表是一种数据结构,用于快速访问和查找数据。在散列表中,元素的存储位置由它们的散列地址决定。当一个元素被插入散列表中时,它的关键字被散列成一个地址,这个地址就是该元素在散列表中的存储位置。然而,由于无法保证每个元素的散列地址都是唯一的,所以不同的元素可能会散列到同一个位置上。 同义词是指散列表中具有相同散列地址的两个元素。当两个元素的关键字被散列成相同的地址时,它们就成了同义词。同义词不一定是相同的元素,它们可能是不同的元素,但它们的关键字相同,因此它们存储在散列表中的位置也相同。 在散列表中,同义词是一个常见的问题。如果散列函数计算散列地址的方法不够好,就容易导致同义词的产生。当散列地址的冲突率较高时,就会出现大量的同义词,这会导致散列表的性能下降。因此,设计一个好的散列函数是非常重要的,它需要尽可能地减少冲突率,从而减少同义词的数量。 在散列表中,处理同义词有很多方法。一种常见的方法是使用开放地址法或者链地址法来处理冲突。开放地址法是指当发生冲突时,继续向下探测散列表,直到找到一个空槽或者是到达散列表的末尾。链地址法是指在每个散列表槽上构建一个链表,当多个元素散列到同一个槽时,它们将被链接到同一个链表上。 总之,在散列表中,同义词是一个常见的问题。为了避免同义词的产生,需要设计好的散列函数并采用合适的处理方法来处理冲突。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值