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

来源:互联网 发布:阿里云国际 信用卡 编辑:程序博客网 时间:2024/06/03 16:44

下载
<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};

地址/数组下标 :key0   :121   :252   :3   :4   :165   :6   :7   :678   :569   :10  :11  :    当存储37(37%12=1)在“1”下标的位置,这就是冲突,然后以开放的心态,那就存在“2”的位置。就这样了。    另一种是解决冲突的方法,linux用到的:        冲突的值放在同一个键下面,多个元素作单链表。查询相同的键时,使用第二特征区别相同键下面的元素。

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

[root@localhost test]# pwd/root/桌面/test[root@localhost test]# lsdata.c  data.h  hashtable.c  hashtable.h  main.c[root@localhost test]# gcc -o main main.c hashtable.c data.c[root@localhost test]# lsdata.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 -32768typedef 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]# lsdata.c  data.h  hashtable.c  hashtable.h  main  main.c[root@localhost test]# ./main count= 12 ,size-nums = 12elem :12 addr is :1elem :67 addr is :8elem :56 addr is :9elem :16 addr is :5elem :25 addr is :2elem :37 addr is :2elem :22 addr is :11elem :29 addr is :6elem :15 addr is :4elem :47 addr is :0elem :48 addr is :1elem :34 addr is :11[root@localhost test]# 
0 0
原创粉丝点击