鉴于博主很久没由跟新过数据结构的内容了,所以博主打算给大家讲解一下哈希表的操作
下面的内容来自于一位老司机 martin的源码,博主在这里借用一下,目的是突出哈希表的原理,明天博主就周末了,也能腾出时间来给上传自己的哈希表的应用。
这个是可以插入字符串的哈希表,一般的都是对数字的操作,所以这个的逼格是很高的!!!!(难点剖析放在最后)
#pragma once
#define DEFAULT_SIZE 16
typedef struct _ListNode
{
struct _ListNode
*next
;
int key
;
void *data
;
}ListNode
;
typedef ListNode
*List
;
typedef ListNode
*Element
;
typedef struct _HashTable
{
int TableSize
;
List
*Thelists
;
}HashTable
;
int Hash(void *key
, int TableSize
);
HashTable
*InitHash(int TableSize
);
void Insert(HashTable
*HashTable
, int key
, void *value
);
Element
Find(HashTable
*HashTable
, const int key
);
void Destory(HashTable
*HashTable
);
void *Retrieve(Element e
);
hash_table
.cpp
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include"hash_table.h"
int Hash(int key
, int TableSize
) {
return (key
%TableSize
);
}
HashTable
*InitHash(int TableSize
){
int i
= 0;
HashTable
*hTable
= NULL;
if (TableSize
<= 0) {
TableSize
= DEFAULT_SIZE
;
}
hTable
= (HashTable
*)malloc(sizeof(HashTable
));
if (NULL == hTable
){
printf("HashTable malloc error.\n");
return NULL;
}
hTable
->TableSize
= TableSize
;
hTable
->Thelists
= (List
*)malloc(sizeof(List
)*TableSize
);
if (NULL == hTable
->Thelists
){
printf("HashTable malloc error\n");
free(hTable
);
return NULL;
}
for (i
= 0; i
< TableSize
; i
++){
hTable
->Thelists
[i
] = (ListNode
*)malloc(sizeof(ListNode
));
if (NULL == hTable
->Thelists
[i
]){
printf("HashTable malloc error\n");
free(hTable
->Thelists
);
free(hTable
);
return NULL;
} else
{
memset(hTable
->Thelists
[i
], 0, sizeof(ListNode
));
}
}
return hTable
;
}
Element
Find(HashTable
*HashTable
, int key
)
{
int i
= 0;
List L
= NULL;
Element e
= NULL;
i
= Hash(key
, HashTable
->TableSize
);
L
= HashTable
->Thelists
[i
];
e
= L
->next
;
while (e
!= NULL && e
->key
!= key
)
e
= e
->next
;
return e
;
}
void Insert(HashTable
*HashTable
, int key
, void *value
)
{
Element e
= NULL, tmp
= NULL;
List L
= NULL;
e
= Find(HashTable
, key
);
if (NULL == e
){
tmp
= (Element
)malloc(sizeof(ListNode
));
if (NULL == tmp
)
{
printf("malloc error\n");
return;
}
L
= HashTable
->Thelists
[Hash(key
, HashTable
->TableSize
)];
tmp
->data
= value
;
tmp
->key
= key
;
tmp
->next
= L
->next
;
L
->next
= tmp
;
} else
printf("the key already exist\n");
}
void Delete(HashTable
*HashTable
, int key
){
Element e
= NULL, last
= NULL;
List L
= NULL;
int i
= Hash(key
, HashTable
->TableSize
);
L
= HashTable
->Thelists
[i
];
last
= L
;
e
= L
->next
;
while (e
!= NULL && e
->key
!= key
) {
last
= e
;
e
= e
->next
;
}
if (e
) {
last
->next
= e
->next
;
delete(e
);
}
}
void *Retrieve(Element e
)
{
return e
? e
->data
: NULL;
}
void Destory(HashTable
*HashTable
)
{
int i
= 0;
List L
= NULL;
Element cur
= NULL, next
= NULL;
for (i
= 0; i
< HashTable
->TableSize
; i
++)
{
L
= HashTable
->Thelists
[i
];
cur
= L
->next
;
while (cur
!= NULL)
{
next
= cur
->next
;
free(cur
);
cur
= next
;
}
free(L
);
}
free(HashTable
->Thelists
);
free(HashTable
);
}
int main(void)
{
char *elems
[] = { "翠花","小芳","苍老师" };
int i
= 0;
HashTable
*HashTable
;
HashTable
= InitHash(31);
Insert(HashTable
, 1, elems
[0]);
Insert(HashTable
, 2, elems
[1]);
Insert(HashTable
, 3, elems
[2]);
Delete(HashTable
, 1);
for (i
= 0; i
< 4; i
++) {
Element e
= Find(HashTable
, i
);
if (e
) {
printf("%s\n", (const char *)Retrieve(e
));
} else {
printf("Not found [key:%d]\n", i
);
}
}
system("pause");
return 0;
}
希望大家能好好的观看我的注释,相信一定能给你收获的。
如果觉得代码太长的,博主在这里给大家将模块分解了。大家也可以观看分解之后的代码,这样
压力会小一点。
头文件就不用说了相信大家都能看明白,就只是声明和定义结构体的类型而已。
哈希函数
int Hash(int key
, int TableSize
) {
return (key
%TableSize
);
}
哈希表的初始化
HashTable
*InitHash(int TableSize
){
int i
= 0;
HashTable
*hTable
= NULL;
if (TableSize
<= 0) {
TableSize
= DEFAULT_SIZE
;
}
hTable
= (HashTable
*)malloc(sizeof(HashTable
));
if (NULL == hTable
){
printf("HashTable malloc error.\n");
return NULL;
}
hTable
->TableSize
= TableSize
;
hTable
->Thelists
= (List
*)malloc(sizeof(List
)*TableSize
);
if (NULL == hTable
->Thelists
){
printf("HashTable malloc error\n");
free(hTable
);
return NULL;
}
for (i
= 0; i
< TableSize
; i
++){
hTable
->Thelists
[i
] = (ListNode
*)malloc(sizeof(ListNode
));
if (NULL == hTable
->Thelists
[i
]){
printf("HashTable malloc error\n");
free(hTable
->Thelists
);
free(hTable
);
return NULL;
} else
{
memset(hTable
->Thelists
[i
], 0, sizeof(ListNode
));
}
}
return hTable
;
}
哈希表中插入元素:
void Insert(HashTable
*HashTable
, int key
, void *value
)
{
Element e
= NULL, tmp
= NULL;
List L
= NULL;
e
= Find(HashTable
, key
);
if (NULL == e
){
tmp
= (Element
)malloc(sizeof(ListNode
));
if (NULL == tmp
)
{
printf("malloc error\n");
return;
}
L
= HashTable
->Thelists
[Hash(key
, HashTable
->TableSize
)];
tmp
->data
= value
;
tmp
->key
= key
;
tmp
->next
= L
->next
;
L
->next
= tmp
;
} else
printf("the key already exist\n");
}
哈希表中查找元素:
Element
Find(HashTable
*HashTable
, int key
)
{
int i
= 0;
List L
= NULL;
Element e
= NULL;
i
= Hash(key
, HashTable
->TableSize
);
L
= HashTable
->Thelists
[i
];
e
= L
->next
;
while (e
!= NULL && e
->key
!= key
)
e
= e
->next
;
return e
;
}
哈希表中删除元素:
void Delete(HashTable
*HashTable
, int key
){
Element e
= NULL, last
= NULL;
List L
= NULL;
int i
= Hash(key
, HashTable
->TableSize
);
L
= HashTable
->Thelists
[i
];
last
= L
;
e
= L
->next
;
while (e
!= NULL && e
->key
!= key
) {
last
= e
;
e
= e
->next
;
}
if (e
) {
last
->next
= e
->next
;
delete(e
);
}
}
哈希表中提取元素以及销毁哈希表:
void *Retrieve(Element e
)
{
return e
? e
->data
: NULL;
}
void Destory(HashTable
*HashTable
)
{
int i
= 0;
List L
= NULL;
Element cur
= NULL, next
= NULL;
for (i
= 0; i
< HashTable
->TableSize
; i
++)
{
L
= HashTable
->Thelists
[i
];
cur
= L
->next
;
while (cur
!= NULL)
{
next
= cur
->next
;
free(cur
);
cur
= next
;
}
free(L
);
}
free(HashTable
->Thelists
);
free(HashTable
);
}
博主认为比较难的就是: 指针数组里面存放的是每个哈希桶的头结点,通过求余来锁定要查找或删除的值在哪一个哈希桶里(认为就是这个最难理解,理解了之后其实哈希就不难了)。其他的就是链表的操作了。
明天上传自己敲得代码