数据结构哈希表(c语言)

  1. 哈希表概念
    决定一个哈希表的主要是哈希函数处理冲突的方法。而按照设定的哈希函数和处理冲突的方法将一组关键字key 映射到有限的地址集合中,这就是哈希表。可以根据处理冲突的方法不同,给哈希表不同的命名,如:链式哈希表,开放址哈希表。

  2. 哈希函数构造方法
    直接定义法:代码块如下:

int hash1(int key){
return a*key + b; //a 缩放, b 平移
}

除留取余法:(我接触最多的)
区间长度为 m 的哈希表,取 不大于 m 的数 x 为模, H(key) = key % p。(理论上,p 取最接近 m 的素数最好了)

int hash2(int key){
return key % p;
}

数字分析法:了解不多,貌似没用到过。
折叠法:
移位折叠

int  hash3(int key){
itn i , j= 1, qu , sum = 0;
for (i = 0; i < w; i++) 
j * = 10;//按照w 位分割
while (key != 0){
qu = key % j;
sum += qu;
key /= j;
}
return sum;
}

平方取中法 :接触的很少(没有)

  1. 处理冲突
    当关键字key的数量大于哈希地址的元素个数时,就一定会产生冲突(几个不同的key 在同一个哈希地址)可以理解为一个关于x , y 的函数, x (key)不同时 , y (地址)是相同的 ,x1 != x2, 但是H(x1) = H(x2),这就是冲突。
    处理冲突的方法:
    链地址法:关键字为同一个地址的链接在同一个单链表中。
    开放地址法:
    Hi=(H(key)+di)% m ( i=1,2,…,n)
    1,线性探测:如果这个地址已经有元素了,就到下一个地址,直到找到空地址或者浏览完全表。
    di = 1,2,3……
    2,二次探测:左右跳跃的看
    di = 12,-12,22-22……
  2. 哈希表的实现
    1,开放地址哈希表(在论坛看了大佬的代码,然后自己思考写了一份,用的是线性探测)
#include 
#include 
//宏定义相关常量
#define Max  10
#define Size  10

typedef struct Sqlist{
int *data;
int length;//长度
}Sqlist;//顺序表

typedef struct HashSqlist{
int *data;
int length;
}HashSqlist;//哈希表

int hash (int key){
return key%10;
}  //哈希函数

void InitSqlist(Sqlist &l){ //这里l 还没定义,所以要加 &
printf("Please int the length of the hashTable\n");
scanf("%d",&l.length);
l.data = (int *)malloc (Max * sizeof(int));
printf("Please int %d numbers\n",l.length);
for (int i = 0; i < l.length ; i ++)
scanf("%d",&l.data[i]);
}//建立一个顺序表,通过顺序表给哈希表赋值

void InitHashSqlist(Sqlist l,HashSqlist &hl){
hl.data = (int *)malloc (Max * sizeof (int ));
hl.length = Size;
int i,j,key;
for (i = 0; i < hl.length; i ++)
hl.data[i] = 0;
for (i = 0; i < l.length ; i ++){
key = hash(l.data[i]);
if (hl.data [key]  != NULL){
for (j = 1;  hl.data[key] != NULL; j ++)
key = hash(l.data[i] + j);
}
hl.data[key] = l.data[i] ;
printf("%d ----%d \n",key,hl.data[key]);//顺便输出,方便检验
}
}

int main (){
Sqlist l;
HashSqlist hl;
InitSqlist(l);
InitHashSqlist(l,hl);
return 0;
}
//目前只是初始化并且输出一个哈希表,有时间(学会后)再补上:查找、删除、替换等功能。

	

链式哈希表

#include  
#include 
#define Max 10
#define Size 10
typedef struct Sqlist {
int *data;
int length;
}Sqlist;

typedef struct HashSqlist{
int *data;
int length;
}HashSqlist;

typedef struct Lnode{
int data;
struct Lnode * next;
}Lnode,*HLinklist; //单链表

typedef struct Hnode {
Lnode *first;
}Hnode,Hlist[Max];//定义一个指向链表第一个地址的哈希链表

typedef struct HashTable{
	 Hlist arr;//哈希表链地址 
	int listNumber;//哈希地址个数 
}HashTable;

int hash(int key ){
return key % 10;
}

void InitSqlist(Sqlist &l){
printf("Please int the length of the hashTable\n");
scanf("%d",&l.length);
l.data = (int *)malloc (Max * sizeof(int ));
printf("Please int %d numbers\n",l.length);
for (int i = 0; i < l.length ; i ++)
scanf("%d",&l.data[i] );
}

void InitHashTable(Sqlist l,HashTable &ht){
Lnode *p,*q;
ht.listNumber = l.length;
int i , j , key;
for (i  = 0; i < ht.listNumber; i ++)
ht.arr[i].first = NULL;
for(i = 0;i < l.length;i++){
		p=(Lnode*)malloc(sizeof(Lnode));
		p->data=l.data[i];
		p->next=NULL;
		key=hash(l.data[i]);
		if (key > ht.listNumber)
		ht.listNumber = key;
		q=ht.arr[key].first;
		if(q){
			while(q->next){
				q=q->next ;
			}
			q->next=p;
		}
		else
			ht.arr[key].first=p;		
	}
	return;	
} 

void Output(HashTable ht){
	int i;
	HLinklist p,q;	
	for(i=0;i<=ht.listNumber;i++){
		p=ht.arr[i].first;
		printf("%d----",i);
		while(p){
			printf("%d->",p->data);
			p=p->next;	
		}
		printf("\n");
	}
	return ;
}

int main(){
 Sqlist l;
 HashTable ht;
 InitSqlist(l);
 InitHashTable(l,ht);// 链地址法解决冲突 
 Output(ht);
 return 0;	
}
//同样的,这个也只实现了初始化并且输出。学会后再更新。

你可能感兴趣的:(数据结构学习小结,数据结构,c语言)