linux内核数据结构-哈希表理解

下载
<1>.散列表

散列表也叫哈希表。以数组结构来作对比,数组中要查询某一个值,得通过一个一个数值的比较。而hashtable是通过某一种关系(func)的映射:【key,value】:
存储地址 = func(关键字)
也就是一种键值关系。找到存储地址,就相当于找到值了,而不像数组需要去比较。实现这样一种对应关系有多种算法。这里以求余数算为例。

存储地址=func(key)=key mod m(p《= m)
m:是散列表长度。

<2>.冲突:
不同的关键字对应同一个存储地址。
本例开放定址法:
例如:买房子,看到价格适中的房子,地段各方面又好的,准备下手,结果被人家抢先了。你怎么办呢?找还没有卖掉的下一家。这也就开明,开放的思想。本例使用此方法。
例子: int nums[12] = {12,67,56,16,25,37,22,29,15,47,48,34};

地址/数组下标 :key
0   :12
1   :25
2   :
3   :
4   :16
5   :
6   :
7   :67
8   :56
9   :
10  :
11  :

    当存储37(37%12=1)在“1”下标的位置,这就是冲突,然后以开放的心态,那就存在“2”的位置。就这样了。

    另一种是解决冲突的方法,linux用到的:
        冲突的值放在同一个键下面,多个元素作单链表。查询相同的键时,使用第二特征区别相同键下面的元素。

注:本书来自《大话数据结构》,只是使用来学习,理解,实践。


[root@localhost test]# pwd
/root/桌面/test
[root@localhost test]# ls
data.c  data.h  hashtable.c  hashtable.h  main.c
[root@localhost test]# gcc -o main main.c hashtable.c data.c
[root@localhost test]# ls
data.c  data.h  hashtable.c  hashtable.h  main  main.c
[root@localhost test]# 

hashtable.h:

#ifndef __HASH_TABLE__
#define __HASH_TABLE__

#define SUCCESS 1
#define UNSUCCESS 0
#define HASHSIZE 12  /*定义散列表的长为数组的长度*/
#define NULLKEY -32768

typedef struct 
{
    int *elem; /*数据元素存储基地址,动态分配数组*/
    int count; /*当前数据元素个数*/
}HashTable;



int InitHashTable(HashTable *H);
int Hash(int key);
void InsertHash(HashTable *H, int key);
int SearchHash(HashTable H, int key, int *addr);

#endif

hashtable.c:

#include <stdlib.h>
#include <stdio.h>
#include "hashtable.h"
#include "data.h"

/*初始化散列表*/
int InitHashTable(HashTable *H)
{

    int i;
    m = HASHSIZE;
    H->count = m;
    H->elem = (int *)malloc(m * sizeof(int));
    for (i = 0;i<m;i++) 
        H->elem[i] = NULLKEY;
    return SUCCESS;

}

/*散列函数*/
int Hash(int key)
{
    return key % m; /*除留余数法*/
}

/*插入关键字进行散列表*/
void InsertHash(HashTable *H, int key)
{
    int addr = Hash(key);/*通过散列函数,求散列地址*/
    while(H->elem[addr] != NULLKEY) /*如果不为空,则冲突*/
        addr = (addr + 1) % m;  /*开放定址法的线性探测*/
    H->elem[addr] = key; /*直到有空位后插入关键字*/
    printf("key:%d, addr:%d, elem:%d\n", key, addr, H->elem[addr]);
}
/*散列表查找关键字*/
int SearchHash(HashTable H, int key, int *addr)
{
    *addr = Hash(key); /*求散列地址*/
    while(H.elem[*addr]!= key) /*如果不为空,则冲突*/
    {
        *addr = (*addr + 1) % m; /*开放定址法的线性探测*/
        if (H.elem[*addr] == NULLKEY || *addr == Hash(key))
        {/*如果循环回到原点*/
            return UNSUCCESS; /*则说明关键字不存在*/
        }
    }
    return SUCCESS;
}

data.h

#ifndef __DATA__
#define __DATA__

extern m;

#endif

data.c

int m = 0; /*散列表表长,全局变量*/

main.c

#include <stdio.h>
#include "hashtable.h"

#include "data.h"


int main()
{

    int i = 0, lennums = 0;
    int nums[12] = {12,67,56,16,25,37,22,29,15,47,48,34};
    int addrresult = 0;
    HashTable hasht;
    InitHashTable(&hasht);
    printf("count= %d ,size-nums = %d\n", hasht.count, sizeof(nums)/sizeof(int));
    lennums = sizeof(nums)/sizeof(int); 

    /*使用查询检测一下*/
    for (i = 0; i < lennums; i++)
    {
        SearchHash(hasht, nums[i], &addrresult);
        printf("elem :%d addr is :%d\n",nums[i],addrresult);
    }
    return 0;

}

输出结果:

[root@localhost test]# ls
data.c  data.h  hashtable.c  hashtable.h  main  main.c
[root@localhost test]# ./main 
count= 12 ,size-nums = 12
elem :12 addr is :1
elem :67 addr is :8
elem :56 addr is :9
elem :16 addr is :5
elem :25 addr is :2
elem :37 addr is :2
elem :22 addr is :11
elem :29 addr is :6
elem :15 addr is :4
elem :47 addr is :0
elem :48 addr is :1
elem :34 addr is :11
[root@localhost test]# 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值