数据结构-哈希表

1、哈希表概念

哈希表支持一种最有效的检索方法:散列。从根本上说,一个哈希表包含一个数组,通过特殊的索引值(键)来访问数组中的元素。哈希表的主要思想是通过一个哈希函数在所有可能的键与槽位之间建立一张映射表。哈希函数每次接受一个键将返回与键位相对应的哈希编码或哈希值,键的数据类型可以多种多样,但是哈希值的类型只能是整型。

2、哈希表的类型

(1)链式哈希表:是指将数据存储在“桶”(bucket)中的哈希表。每个“桶”都是一个链表,且链表的容量能够随着冲突的增加而增大。

(2)开地址哈希表:是指将数据存储在本身中,而不是“桶”中的哈希表,它通过各种探查方法来避免冲突问题。

3、哈希表的主要应用

数据库系统、符号表、标签缓冲区、数据字典、关联数组

4、哈希表的实现代码

(1)链式哈希表

/*chtlb.h*/
#ifndef CHTBL_H
#define CHTBL_H

#include <stdlib.h>
#include "list.h"

/*define a structure for chained hash table*/
typedef struct CHTbl_
{
	int		buckets;
	int		(*h)(const void *key);
	int		(*match)(const void *key1,const void *key2);
	void	(*destroy)(void *data);
	int		size;
	List	*table;
}CHTbl;

/*public interface*/
int chtbl_init(CHTbl *htbl,int buckets,int (*h)(const void *key),
			   int (*match)(const void *key1,const void *key2),void (*destroy)(void *data));
void chtbl_destroy(CHTbl *htbl);
int chtbl_insert(CHTbl *htbl,const void *data);
int	chtbl_remove(CHTbl *htbl,void **data);
int chtbl_lookup(const CHTbl *htbl,void **data);
#define chtbl_size(htbl)	((htbl)->size)

#endif


 

/*chtbl.c*/
#include <stdlib.h>
#include <string.h>
#include "list.h"
#include "chtbl.h"



int chtbl_init(CHTbl *htbl,int buckets,int (*h)(const void *key),
			   int (*match)(const void *key1,const void *key2),void (*destroy)(void *data))
{
	int i;

	/*alloate space for the hash table*/
	if((htbl->table=(List *)malloc(buckets*sizeof(List)))==NULL)
		return -1;

	/*initialize the buckets*/
	htbl->buckets=buckets;
	for(i=0;i<htbl->buckets;i++)
		list_init(&htbl->table[i],destroy);

	/*encapsulate the function*/
	htbl->h=h;
	htbl->match=match;
	htbl->destroy=destroy;

	/*initialize the number of elements in the table*/
	htbl->size=0;
	return 0;
}


void chtbl_destroy(CHTbl *htbl)
{
	int i;

	/*destroy each buckets*/
	for(i=0;i<htbl->buckets;i++)
	{
		list_destroy(&htbl->table[i]);
	}

	/*free the storage alloctee for the hash table*/
	free(htbl->table);

	/*clear the structure sa precatution*/
	memset(htbl,0,sizeof(CHTbl));
	return ;

}


int chtbl_insert(CHTbl *htbl,const void *data)
{
	void *temp;
	int  bucket,retval;

	/*do nothing if the data is already in the table*/
	temp=(void *)data;
	if(chtbl_lookup(htbl,&temp)==0)
		return 1;

	/*hash the key*/
	bucket=htbl->h(data)%htbl->buckets;

	/*insert the data into the bucket*/
	if((retval=list_ins_next(&htbl->table[bucket],NULL,data))==0)
		htbl->size++;
	return retval;
}


int	chtbl_remove(CHTbl *htbl,void **data)
{
	ListElmt *element,*prev;
	int bucket;

	/*hash the key*/
	bucket=htbl->h(*data)%htbl->buckets;

	/*search for the data in the bucket*/
	prev=NULL;
	for(element=list_head(&htbl->table[bucket]);element!=NULL;element=list_next(element))
	{
		if(htbl->match(*data,list_data(element)))
		{
			/*remove the data from the bucket*/
			if(list_rem_next(&htbl->table[bucket],prev,data)==0)
			{
				htbl->size++;
				return 0;
			}
			else
			{
				return -1;
			}
		}
		prev=element;
	}

	/*return that the data was not found*/
	return -1;
}


int chtbl_lookup(const CHTbl *htbl,void **data)
{
		ListElmt *element ;
	    int bucket;

	/*hash the key*/
	bucket=htbl->h(*data)%htbl->buckets;

	/*search for the data in the bucket*/
	for(element=list_head(&htbl->table[bucket]);element!=NULL;element=list_next(element))
	{
		if(htbl->match(*data,list_data(element)))
		{
			/*pass back the data from the table*/
			*data=list_data(element);
			return 0;
		
		}
	}

	/*return that the data was not found*/
	return -1;

}


 

应用实例:

后续补上

(2)开地址哈希表

/*ohtbl.h*/
#ifndef OCHTBL_H
#define OCHTBL_H

#include <stdlib.h>

/*define a structure for open-address hash table*/
typedef struct OHTbl_
{
	int		positions;
	void	*vacated;
	int		(*h1)(const void *key);
	int		(*h2)(const void *key);
	int		(*match)(const void *key1,const void *key2);
	void	(*destroy)(void *data);
	int		size;
	void	**table;
}OHTbl;

/*public interface*/
int ohtbl_init(OHTbl *htbl,int positions,int (*h1)(const void *key),int(*h2)(const void *key),
			   int (*match)(const void *key1,const void *key2),void (*destroy)(void *data));
void ohtbl_destroy(OHTbl *htbl);
int ohtbl_insert(OHTbl *htbl,const void *data);
int	ohtbl_remove(OHTbl *htbl,void **data);
int ohtbl_lookup(const OHTbl *htbl,void **data);
#define ohtbl_size(htbl)	((htbl)->size)

#endif


 

/*ohtbl.c*/
#include <stdlib.h>
#include <string.h>
#include "ohtbl.h"

/*reserve a sentinel memory address for vacated element*/
static char vacated;


int ohtbl_init(OHTbl *htbl,int positions,int (*h1)(const void *key),int (*h2)(const void *key),
			   int (*match)(const void *key1,const void *key2),void (*destroy)(void *data))
{
	int i;

	/*alloate space for the hash table*/
	if((htbl->table=(void **)malloc(positions*sizeof(void *)))==NULL)
		return -1;

	/*initialize the buckets*/
	htbl->positions=positions;
	for(i=0;i<htbl->positions;i++)
		 htbl->table[i]=NULL;

	/*set the vacated member to the sentinel memory address reserved for this*/
	htbl->vacated=&vacated;

	/*encapsulate the function*/
	htbl->h1=h1;
	htbl->h2=h2;
	htbl->match=match;
	htbl->destroy=destroy;

	/*initialize the number of elements in the table*/
	htbl->size=0;
	return 0;
}


void ohtbl_destroy(OHTbl *htbl)
{
	int i;

	if(htbl->destroy!=NULL)
	{
		/*call a user-defined function to free dynamically allocated data*/
		for(i=0;i<htbl->positions;i++)
		{
			if(htbl->table[i]!=NULL && htbl->table[i]!=htbl->vacated)
			htbl->destroy(&htbl->table[i]);
		}
	}

	/*free the storage alloctee for the hash table*/
	free(htbl->table);

	/*clear the structure sa precatution*/
	memset(htbl,0,sizeof(OHTbl));
	return ;

}


int ohtbl_insert(OHTbl *htbl,const void *data)
{
	void *temp;
	int  i,position;

	/*do not exceed the number of positions in the table*/
	if(htbl->size==htbl->positions)
		return -1;
    
    /*do nothing if the data is already in the table*/
	temp=(void *)data;
	if(ohtbl_lookup(htbl,&temp)==0)
		return 1;

	/*use double hashing to hash the key*/
	for(i=0;i<htbl->positions;i++)
	{
		position=(htbl->h1(data)+(i*htbl->h2(data)))%htbl->positions;
		if(htbl->table[position]==NULL ||htbl->table[position]==htbl->vacated)
		{
			/*insert the data into the table*/
			htbl->table[position]=(void *)data;
			htbl->size++;
			return 0;
		}
	}
	
	/*return that the hash function were selecte incorrectly*/
	return -1;
}


int ohtbl_remove(OHTbl *htbl,void **data)
{
	int position,i;

	/*use double hashing to hash the key*/
	for(i=0;i<htbl->positions;i++)
	{
		position=(htbl->h1(data)+(i*htbl->h2(data)))%htbl->positions;
		if(htbl->table[position]==NULL)  
		{
			/*return that the data was not found*/
			return -1;
		}
		else if(htbl->table[position]==htbl->vacated)
		{
			/*search beyond vacated from the table*/
			continue;
		}
		else if(htbl->match(htbl->table[position],*data))
		{
			/*pass back the data from the table*/
			*data=htbl->table[position];
			htbl->table[position]=htbl->vacated;
			htbl->size--;
			return 0;
		}
	}

	/*return that the data was not found*/
	return -1;
}


int ohtbl_lookup(const OHTbl *htbl,void **data)
{
	int position,i;

	/*use double hashing to hash the key*/
	for(i=0;i<htbl->positions;i++)
	{
		position=(htbl->h1(data)+(i*htbl->h2(data)))%htbl->positions;
		if(htbl->table[position]==NULL)  
		{
			/*return that the data was not found*/
			return -1;
		}
		else if(htbl->match(htbl->table[position],*data))
		{
			/*pass back the data from the table*/
			*data=htbl->table[position];
			return 0;
		}
	}

	/*return that the data was not found*/
	return -1;

}


 

应用实例:

后续补上

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值