腾讯三面的时候,叫我写了个哈希表,当时紧张没写好···结果跪了···

  回来后粪发涂墙,赶紧写了一个!

  什么都不说了···先让我到厕所里面哭一会···

  %>_<%

  果然现场发挥,以及基础扎实才是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)的更多相关文章

  1. 算法与数据结构基础 - 哈希表(Hash Table)

    Hash Table基础 哈希表(Hash Table)是常用的数据结构,其运用哈希函数(hash function)实现映射,内部使用开放定址.拉链法等方式解决哈希冲突,使得读写时间复杂度平均为O( ...

  2. PHP关联数组和哈希表(hash table) 未指定

    PHP有数据的一个非常重要的一类,就是关联数组.又称为哈希表(hash table),是一种很好用的数据结构. 在程序中.我们可能会遇到须要消重的问题,举一个最简单的模型: 有一份username列表 ...

  3. 词典(二) 哈希表(Hash table)

    散列表(hashtable)是一种高效的词典结构,可以在期望的常数时间内实现对词典的所有接口的操作.散列完全摒弃了关键码有序的条件,所以可以突破CBA式算法的复杂度界限. 散列表 逻辑上,有一系列可以 ...

  4. 数据结构 哈希表(Hash Table)_哈希概述

    哈希表支持一种最有效的检索方法:散列. 从根来上说,一个哈希表包含一个数组,通过特殊的索引值(键)来访问数组中的元素. 哈希表的主要思想是通过一个哈希函数,在所有可能的键与槽位之间建立一张映射表.哈希 ...

  5. 什么叫哈希表(Hash Table)

    散列表(也叫哈希表),是根据关键码值直接进行访问的数据结构,也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度.这个映射函数叫做散列函数,存放记录的数组叫做散列表. - 数据结构 ...

  6. 哈希表(Hash table)

  7. Redis原理再学习04:数据结构-哈希表hash表(dict字典)

    哈希函数简介 哈希函数(hash function),又叫散列函数,哈希算法.散列函数把数据"压缩"成摘要,有的也叫"指纹",它使数据量变小且数据格式大小也固定 ...

  8. Hash表 hash table 又名散列表

    直接进去主题好了. 什么是哈希表? 哈希表(Hash table,也叫散列表),是根据key而直接进行访问的数据结构.也就是说,它通过把key映射到表中一个位置来访问记录,以加快查找的速度.这个映射函 ...

  9. [译]C语言实现一个简易的Hash table(4)

    上一章我们解释了Hash table中最重要的hash函数,并用伪代码和C语言实现了一个我们自己的hash函数,hash函数中碰撞是无法避免的,当发生碰撞时我们改如何有效的处理呢?这章我们就来讲解下. ...

随机推荐

  1. *IDEA真好用

    使用maven做开发,在编辑pom.xml文件时

  2. swift:高级运算符(位运算符、溢出运算符、优先级和结合性、运算符重载函数)

    swift:高级运算符 http://www.cocoachina.com/ios/20140612/8794.html 除了基本操作符中所讲的运算符,Swift还有许多复杂的高级运算符,包括了C语和 ...

  3. PCL—低层次视觉—关键点检测(NARF)

    关键点检测本质上来说,并不是一个独立的部分,它往往和特征描述联系在一起,再将特征描述和识别.寻物联系在一起.关键点检测可以说是通往高层次视觉的重要基础.但本章节仅在低层次视觉上讨论点云处理问题,故所有 ...

  4. (转)Spring的编程式事务例子

    纯JDBC操作, 对某些项目来说, 也许更好, Spring JDBC Framework让你不用关心Connection, Statement, ResultSet. 定义数据源 spring事务编 ...

  5. [前端]利用a标签获取url里所需的内容

    function parseURL(url) { var a = document.createElement('a'); a.href = url; return { source: url, pr ...

  6. C# 写入XML文档三种方法详细介绍

      三个类将同样的xml内容写入文档,介绍了如何使用XmlDocument类对XML进行操作,以及如何使用LINQ to XML对XML进行操作. 它们分别使用了XmlDocument类和XDocum ...

  7. C语言中的宏展开

    #include<stdio.h> #define f(a,b) a##b #define g(a) #a #define h(a) g(a) int main() { printf(,) ...

  8. Java中静态代码块,代码块,构造方法优先级、区别及代码示例

    在项目中遇到了代码块的知识点,跑了下测试,写下结论 代码优先级:静态代码块 -> 构造代码块 -> 构造方法 多个代码块优先级,按照“先定义的代码先执行,后定义的代码后执行”原则执行 静态 ...

  9. Android开发之获取系统版本号

    获取系统版本号:获取当前系统的版本号: textView.setText("Product Model: " + android.os.Build.MODEL + ",& ...

  10. JAVA中获取工程路径的方法

    在jsp和class文件中调用的相对路径不同.在jsp里,根目录是WebRoot 在class文件中,根目录是WebRoot/WEB-INF/classes 当然你也可以用System.getProp ...