数据结构——杂凑表(拉链法)

本文介绍了一种基于链地址法解决冲突的哈希表实现方法,并提供了完整的C语言源代码示例。通过直接定址法构造哈希函数,演示了哈希表的基本操作,包括创建、插入、查找及删除等。

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

Hash
设某元素的关键字为key,用函数Hash(key)的值作为该元素的地址,所构造的查找表称为哈希表(或散列表),函数Hash(key)称为哈希(Hash)函数(或散列函数)。
若两个关键字k1 != k2,但H(k1) = H(k2)。这种现象称为冲突,k1和k2称为同义词。
要避免冲突,需要构造一个恰当的哈希函数。常见的构造哈希函数的方法有:直接定址法、除留余数法、平方取中法等。
有时冲突是不能完全避免的,须妥善处理。
处理冲突的方法:链地址法(拉链法)、开放定址法
链地址法(拉链法)
将所有发生冲突的元素存储在一个链表中,并将这些链表的表头指针存放在一个表中。所构造的散列表称为开散列表。
插入操作的最坏情况运行时间为O(1),查找操作的最坏情况运行时间与表的长度成正比。


ChainedHashMain.c

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

/*简单操作示例*/
int main(int argc, char **argv)
{
    CHashTable t;
    CHashNode 
*p;
    
int a[N] = {47729111692228303789421};

    ChainedHashCreate(
&t, a);
    printf(
"[+] hash table create ok. ");

    p 
= ChainedHashSearch(&t, 92);
    PrintNodeKey(p);

    ChainedHashInsert(
&t, 92);

    ChainedHashDelete(
&t, 92);
    p 
= ChainedHashSearch(&t, 92);
    PrintNodeKey(p);

    
return 1;
}

 

hash.h
#ifndef _HASH_H
#define _HASH_H

#define M 11
#define N 14
#define DELETE -1

typedef 
int KeyType;
typedef 
struct Node{
    KeyType key;
    
struct Node *next;
}
CHashNode;
typedef CHashNode 
*CHashTable[M];

int Hash(KeyType k);
int ChainedHashInsert(CHashTable *t, KeyType k);
int ChainedHashCreate(CHashTable *t, int *a);
int ChainedHashDelete(CHashTable *t, KeyType k);
CHashNode 
*ChainedHashSearch(CHashTable *t, KeyType k);
void PrintNodeKey(CHashNode *ph);

#endif

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

int Hash(KeyType k)
{
    
return k % M;
}


/*
 *根据a[0..N-1]中结点建立散列表t[0..M-1]
 
*/

int ChainedHashCreate(CHashTable *t, int *a)
{
    
int i;

    
for(i = 0; i < M; i++)
        (
*t)[i] = NULL;
    
for(i = 0; i < N; i++)
        ChainedHashInsert(
&(*t), a[i]);

    
return 1;
}


/*
 *将关键字k插入散列表t中
 
*/

int ChainedHashInsert(CHashTable *t, KeyType k)
{
    CHashNode 
*p;
    
int addr;

    p 
= ChainedHashSearch(&(*t), k);
    
if(p)
    
{
        printf(
"Duplicate Key! ");

        
return 0;
    }

    
else
    
{
        addr 
= Hash(k);
        p 
= (CHashNode *)malloc(sizeof(CHashNode));
        p
->key = k;
        p
->next = (*t)[addr];
        (
*t)[addr] = p;

        
return 1;
    }

}


/*
 *在散列表t中查找关键字k
 
*/

CHashNode 
*ChainedHashSearch(CHashTable *t, KeyType k)
{
    CHashNode 
*p;
    
int addr;

    addr 
= Hash(k);
    p 
= (*t)[addr];
    
if(p == NULL)
    
{
        
return NULL;
    }

    
else
    
{
        
while(p && p->key != k)
            p 
= p->next;

        
return p;
    }

}


/*
 *在散列表t中删除关键字k
 
*/

int ChainedHashDelete(CHashTable *t, KeyType k)
{
    CHashNode 
*p, *q;
    
int addr;

    addr 
= Hash(k);
    p 
= (*t)[addr];
    
if((p == NULL) || (p->key == DELETE))
    
{
        printf(
"No such key! ");
        
return 0;
    }

    
else
    
{
        q 
= p;
        
while(p && p->key != k)
        
{
            q 
= p;
            p 
= p->next;
        }

        
if(q != p)
            q
->next = p->next;
        
else
            p
->key = DELETE;

        
return 1;
    }

}


void PrintNodeKey(CHashNode *p)
{
    
if(p == NULL)
        printf(
"It's a NULL node! ");
    
else
        printf(
"%d ", p->key);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值