C语言-简单哈希表(hash table)
腾讯三面的时候,叫我写了个哈希表,当时紧张没写好···结果跪了···
回来后粪发涂墙,赶紧写了一个!
什么都不说了···先让我到厕所里面哭一会···
%>_<%
果然现场发挥,以及基础扎实才是important的!
用链地址法解决冲突的哈希表(C语言,VS2008编写、测试):
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h> struct node {
int count; // count the same value
char *value;
node *next;
}; // 使用链地址法解决冲突
struct hash_table {
int size; // table size
node **list; // 链表队列一条链为一个散列位置
}; //==================================================//
// declare int hash_func(char *str, int tableSize);
hash_table *hash_table_init(int tableSize);
node *hash_table_new_node(char *str, int len);
int hash_table_insert(char *str, struct hash_table * head);
node *hash_table_find(char *str, struct hash_table * head);
void hash_table_clear(struct hash_table * head);
void hash_table_print(hash_table *head); //==================================================//
// realize // hash function: return the position of str in the hash table
int hash_func(char *str, int tableSize) {
unsigned int hashVal = ; while (*str != '\0')
hashVal += (hashVal << ) + *str++; return hashVal % tableSize;
} // init & create hash table
hash_table *hash_table_init(int tableSize) {
hash_table *head; head = (hash_table *)malloc(sizeof(hash_table));
if (NULL == head)
return NULL;
// 元素总数量尽可能为素数,以保证mod尽可能均匀
head->size = tableSize; // 链表队列中,一条链为一个散列位置
head->list = (node **)malloc(sizeof(node *) * tableSize); // initialize each hash list
int i;
for (i = ; i < head->size; i++)
head->list[i] = NULL; return head;
} // return one new node
node *hash_table_new_node(char *str, int len) {
node *newNode = (node *)malloc(sizeof(node));
newNode->count = ;
newNode->next = NULL;
newNode->value = (char *)malloc(len + );
memset(newNode->value, , len + );
memcpy(newNode->value, str, len); return newNode;
} // insert one node into hash table
int hash_table_insert(char *str, hash_table *head) {
int len = strlen(str);
// get str's position in the hash table
int pos = hash_func(str, head->size); printf("[insert] %s at pos: %d\n", str, pos); // locate list
node *q = head->list[pos], *p = head->list[pos];
for ( ; p != NULL; p = p->next) {
if (memcmp(p->value, str, len) == ) {
p->count++; // found the same value, count+1
return pos;
}
q = p; // store the previous node
} // if not found, then insert one new node
node *newNode = hash_table_new_node(str, len);
/*
//===================================================================//
// method 1:
// TODO: 如果是字符串不同,但是哈希值一样呢???貌似没考虑到这种情况
// insert into the head of list
newNode->next = head->list[pos];
head->list[pos] = newNode;
*/
//===================================================================//
// method 2:
// insert into the tail of list
// 由于p指向了NULL,所以要插入链表尾的话,就必须增加一个变量q记录p前一个节点位置
if (NULL == q) {
newNode->next = head->list[pos];
head->list[pos] = newNode;
} else {
q->next = newNode;
newNode->next = NULL;
} return pos;
} // find the node which stored str & return it
node *hash_table_find(char *str, hash_table *head) {
if (NULL == head)
return NULL; int pos = hash_func(str, head->size);
node *p = head->list[pos]; int len = strlen(str); for ( ; p != NULL; p = p->next)
if (memcmp(p->value, str, len) == )
break;//return p; // found & return return p; //return NULL;
} // clear the whole hash table
void hash_table_clear(hash_table *head) {
if (NULL == head)
return; node *p = NULL, *q = NULL; int i;
for (i = ; i < head->size; i++) {
p = head->list[i];
while (p != NULL) {
p->count = ; // TODO: test
q = p->next;
// free value
if (p->value) {
free(p->value);
p->value = NULL;
}
// free current node
if (p) {
free(p);
p = NULL;
}
// point to next node
p = q;
}
}
// free list
if (head->list) {
free(head->list);
head->list = NULL;
}
// free head
if (head) {
free(head);
head = NULL;
}
} // print the whole hash table
void hash_table_print(hash_table *head) {
if (NULL == head) {
printf("hash table is NULL! \n");
return;
} int i;
node *p = NULL; for ( i = ; i < head->size; i++) {
p = head->list[i];
printf("//============list %d============//\n", i);
while (p != NULL) {
if (p->value)
printf("%s:%d ", p->value, p->count);
else
printf("(NULL):(0) ");
p = p->next;
}
printf("\n");
}
} // test
int main() {
// create
hash_table *head = hash_table_init(); // insert
hash_table_insert("test 1", head);
hash_table_insert("test 2", head);
hash_table_insert("test 2", head);
hash_table_insert("test 3", head);
hash_table_insert("test 4", head); hash_table_print(head); // find
node *find = hash_table_find("test 2", head);
printf("\n[Find] %s:%d\n\n", find->value, find->count); // clear
hash_table_clear(head); hash_table_print(head); // create
head = hash_table_init(); // insert
hash_table_insert("test 1", head);
hash_table_insert("test 2", head);
hash_table_insert("test 2", head);
hash_table_insert("test 3", head);
hash_table_insert("test 4", head); hash_table_print(head); return ;
}
C语言-简单哈希表(hash table)的更多相关文章
- 算法与数据结构基础 - 哈希表(Hash Table)
Hash Table基础 哈希表(Hash Table)是常用的数据结构,其运用哈希函数(hash function)实现映射,内部使用开放定址.拉链法等方式解决哈希冲突,使得读写时间复杂度平均为O( ...
- PHP关联数组和哈希表(hash table) 未指定
PHP有数据的一个非常重要的一类,就是关联数组.又称为哈希表(hash table),是一种很好用的数据结构. 在程序中.我们可能会遇到须要消重的问题,举一个最简单的模型: 有一份username列表 ...
- 词典(二) 哈希表(Hash table)
散列表(hashtable)是一种高效的词典结构,可以在期望的常数时间内实现对词典的所有接口的操作.散列完全摒弃了关键码有序的条件,所以可以突破CBA式算法的复杂度界限. 散列表 逻辑上,有一系列可以 ...
- 数据结构 哈希表(Hash Table)_哈希概述
哈希表支持一种最有效的检索方法:散列. 从根来上说,一个哈希表包含一个数组,通过特殊的索引值(键)来访问数组中的元素. 哈希表的主要思想是通过一个哈希函数,在所有可能的键与槽位之间建立一张映射表.哈希 ...
- 什么叫哈希表(Hash Table)
散列表(也叫哈希表),是根据关键码值直接进行访问的数据结构,也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度.这个映射函数叫做散列函数,存放记录的数组叫做散列表. - 数据结构 ...
- 哈希表(Hash table)
- Redis原理再学习04:数据结构-哈希表hash表(dict字典)
哈希函数简介 哈希函数(hash function),又叫散列函数,哈希算法.散列函数把数据"压缩"成摘要,有的也叫"指纹",它使数据量变小且数据格式大小也固定 ...
- Hash表 hash table 又名散列表
直接进去主题好了. 什么是哈希表? 哈希表(Hash table,也叫散列表),是根据key而直接进行访问的数据结构.也就是说,它通过把key映射到表中一个位置来访问记录,以加快查找的速度.这个映射函 ...
- [译]C语言实现一个简易的Hash table(4)
上一章我们解释了Hash table中最重要的hash函数,并用伪代码和C语言实现了一个我们自己的hash函数,hash函数中碰撞是无法避免的,当发生碰撞时我们改如何有效的处理呢?这章我们就来讲解下. ...
随机推荐
- Hibernate逍遥游记-第9章 Hibernate的映射类型
1. 2. <?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate ...
- WCF入门(九)--WCF实例管理
这组由Windows通讯基础(WCF)结合一组消息(客户端请求)服务实例所采用的技术被称为实例管理.一个完全由三种类型实例激活支持WCF,它们如下所述. 1.每个调用服务 每次调用服务是Windows ...
- HDU2521反素数
只是了解下这种简单的数论定义,解释可以戳这个 http://www.cnblogs.com/Findxiaoxun/p/3460450.html ,然后按Ctrl+ F搜索 反素数 ,找到那一部 ...
- JS代码片段:一个日期离现在多久了
var dateDiff = function(hisTime,nowTime){ if(!arguments.length) return ''; var arg = arguments, now ...
- apk反编译(3)smali语法
from http://pallergabor.uw.hu/androidblog/dalvik_opcodes.html Dalvik opcodes Author: Gabor Paller Vx ...
- Java开发工具MyEclipse的设置自动联想功能
最近初学Java,正在使用MyEclipse来编写新的项目,刚开始打开MyEclipse感觉这个工具既陌生又熟悉,熟悉之处在于编辑器的几大共通之处它都具备,比如说基本的设置.编辑区.调试区都是类似的, ...
- java单元测试(使用junit)
JUnit是由 Erich Gamma 和 Kent Beck 编写的一个回归测试框架(regression testing framework),供Java开发人员编写单元测试之用. 1.概述 Ju ...
- OEM - emctl resetTZ agent 设置时区
[oracle@redhat4 config]$ cd $ORACLE_HOME/redhat4.7_orcl/sysman/config [oracle@redhat4 config]$ pwd/u ...
- HDU 4893 线段树
比赛时太大意,斐波拉契数列开小了. 题目大意:1个序列,3种操作,改变序列某个数大小,将序列中连续的一段每个数都变成其最近的斐波拉契数,以及查询序列中某一段的数之和. 解题思路:维护add[]数组表示 ...
- C# winform 窗体从右下角向上弹出窗口效果
参考自 http://blog.csdn.net/yilan8002/article/details/7197981 /// <summary> /// 窗体动画函数 注意:要引用Syst ...