散列表-链接法解决冲突

本文探讨了散列技术,使用除留余数法设计散列函数,并通过链接法解决冲突。每个槽位的链表是带头结点的双向链表。关键在于选取合适的除数m,例如在处理2000个字符串时,选择质数701作为m,以保持较低的装填因子并避免接近2的整数幂。不成功的查找平均检查3个元素。参考链接提供了更多相关信息。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

散列,散列函数采用除留余数法,解决冲突使用链接法,每个槽的链表为带头结点的双向链表。使用这种方法的关键是选择一个合适的除数m,可以选择m是与2的整数幂不太接近的质数(主要是在将字符串转化为整数的过程中)。例如,如果哈希表中要存放2000个字符串,每个字符有8位,一次不成功的查找需要大约检查3个元素。则可以选择m=701,因为接近于装填因子a=2000/3,并且701离2的整数幂都不太近(512(2^9)<m<1024(2^10))

相关资料:

http://baike.baidu.com/view/1320746.htm

http://blog.youkuaiyun.com/flowshell/article/details/5996983

/*链接法解决哈希散列碰撞问题*/
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>

#define N 20      //数组数量 
#define Nhash 7  //哈希槽的数量 
#define N_R 200

//每个数据结点 
typedef struct node{
    int key;
    int num;
    struct node * next;
    struct node * pre;
}Node, *Pnode;

//哈希链表 
typedef struct Hash{
    Pnode link[N]; //每个链表的表头指针 
    int num;    //哈希表中现存数据 
    int len;     //哈希数组长度 
}hash,*Phash;

Pnode IniPnode(int key){
    Pnode p=(Pnode)malloc(sizeof(Node));
    p->key=key;
    p->num=1;
    p->next=NULL;
    p->pre=NULL;
}

//散列位置计算,当前使用取余数法 
int HashPos(int key){
    return key % Nhash;
}

Pnode FindNodePos(Phash h, int key){
    int pos=HashPos(key);
    Pnode link = h->link[pos];
    while(link->next != NULL && link->key != key){
        link=link->next;
    }
    return link;   
}

void IniHash(Phash *h, int len){
    int i;
    *h=(Phash)malloc(sizeof(hash));
    for(i=0;i<len;i++){
        (*h)->link[i] = IniPnode(-1); //头结点 
    }
    (*h)->num =0;  //总数为0 
    (*h)->len=len;
}

void Insert(Phash h, int key){
    Pnode p=FindNodePos(h,key);
    if(p->next != NULL) p->num ++;
    else{
        Pnode q =IniPnode(key);
        p->next = q;
        q->pre=p;      
    } 
     ++ h->num ;
}

Pnode Search(Phash h, int key){
    Pnode p=FindNodePos(h,key);
    if(p->next = NULL) return NULL;
    else return p;    
}

int Delete(Phash h, int key){
    Pnode p=FindNodePos(h,key);
    p->pre->next=p->next;
    free(p);
} 

void PrintLink(Pnode p){
    while(p->next!=NULL){
        printf("[key=%d|num=%d] -> ",p->next->key,p->next->num);
        p=p->next;
    }
    //printf("[key=%d|num=%d]",p->key,p->num);
    printf("\n");
}

void PrintHash(Phash h){
    int i;
    printf("哈希表中公有结点%d个\n",h->num);
    for(i=0;i<h->len;i++){
        printf("%d\t",i);
        PrintLink(h->link[i]);
    }
}

void DeleteHash(Phash h){
    int i;
    for(i=0;i<h->num;i++){
        free(h->link[i]);
    }
    free(h); 
}
    
int main(){
    int i, a[N];
    Phash h=NULL; //哈希数组链表头结点  
    IniHash(&h,Nhash);  
           
    srand((unsigned)time(NULL));    
    for(i=0;i<N;i++){
        a[i]=rand()%N_R;
        Insert(h,a[i]);
        printf("%d ",a[i]);       
    }
    printf("\n"); 
    PrintHash(h);
    for(i=0;i<N;i++){
        Delete(h,a[i]);
    }       
    DeleteHash(h); 
    system("pause");
    return 0;
} 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值