一个哈希表的实现
来源:互联网 发布:替换电脑软件图标 编辑:程序博客网 时间:2024/04/27 13:48
一个哈希表的实现
转:http://blog.csdn.net/shuqin1984/article/details/6587503
哈希表是数组、链表及数学算法的一个综合应用, 无论在理论上还是实践上都是非常有价值的。 废话不多说了, 贴上自己的实现吧,以供参考,有错误之处,恳请指出。 还需要做的一个工作是, 为实现中用到的链表和哈希表设计详尽苛刻的测试。
该哈希表包括四个文件: common.h , LinkList.c, Hashtable.c , main.c . 将它们放在同一个文件夹中,按照下面的方式编译运行
$ gcc -Wall *.c -o main
$ main
或者 一个简单的 makefile 文件:
OBJS = Hashtable.o main.o LinkList.o
mhash: $(OBJS)
[tab]cc -o mhash $(OBJS)
HashSearch.o: Hashtable.c common.h
[tab]cc -c Hashtable.c
main.o: main.c common.h
[tab]cc -c main.c
LinkList.o: LinkList.c common.h
[tab]cc -c LinkList.c
.PHONY: clean
clean:
[tab]-rm $(OBJS) mhash
$ make
$ mhash
下面是各个文件的具体实现:
common.h
- /*
- * common.h
- * 关于哈希查找和链表结构的声明和定义。
- *
- * 哈希查找法:
- * 采用字符串散列函数的哈希函数和链地址法的冲突解决方案
- *
- */
- enum { OK = 1, ERROR = 0, TRUE = 1, FALSE = 0, FAILURE = 1, LEN_OF_TABLE = 13, RECORD_NUM = 95 };
- typedef struct { /* 记录类型 */
- char *key;
- int value;
- } Record;
- typedef struct node *LLNptr;
- typedef struct node { /* 链表结点类型 */
- Record data;
- LLNptr next;
- } LLNode;
- typedef int Status;
- /* 单链表的函数声明,主要依照严蔚敏老师《数据结构C语言版》中的描述 */
- Status InitList(LLNptr *list); /* 创建带头结点的单链表 */
- int IsEmpty(LLNptr list); /* 判断单链表是否为空 */
- int ListLength(LLNptr list); /* 返回链表长度,即记录的数目(不含头结点) */
- Status GetRecord(LLNptr list, int i, Record *e); /* 返回链表中第 i 个位置上的结点,并保存在 e 中 */
- Status ListInsert(LLNptr list, int i, Record e); /* 将记录 e 插入到链表 list 中的第 i 个位置上 */
- Status ListDelete(LLNptr list, int i, Record *e); /* 将链表 list 中的第 i 个位置上的记录删除,并用 e 返回 */
- Status ListTraverse(LLNptr list, void (*visit)(Record *e)); /* 使用 visit 遍历链表 */
- Status ListPrint(LLNptr list); /* 打印链表内容 */
- void printRecord(Record *e); /* 打印记录内容 */
- int Equal(Record *e1, Record *e2); /* 判断记录的相等性 */
- /* 返回链表 list 中与 e 满足 compare 关系的记录的指针; 如果不存在,返回 NULL */
- Record* PLocateRecord(LLNptr list, Record e, int (*compare)(Record *e1, Record *e2));
- /* 哈希查找的函数声明 */
- int hash(char* key); /* 计算关键字的哈希值 */
- Status InitTable(LLNptr hashtable[]); /* 初始化哈希表 hashtable */
- Status HashInsert(LLNptr hashtable[], Record e); /* 将记录插入哈希表 hashtable 中 */
- Record* HashSearch(LLNptr hashtable[], Record e); /* 根据记录关键字查找:若有则返回指向该记录的指针,否则返回 NULL */
- Status HashTraverse(LLNptr hashtable[]); /* 遍历哈希表 */
LinkList.c
- /* LinkList.c */
- /* 带头结点的单链表实现,头结点存储表长信息 */
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include "common.h"
- Status InitList(LLNptr* list)
- {
- LLNptr head = (LLNptr)malloc(sizeof(LLNode));
- if (!head) {
- fprintf(stderr, "Error: fail to allocate memory!\n");
- return ERROR;
- }
- head->data.value = 0; /* 头结点的 value 域存储表长 */
- head->data.key = NULL; /* 头结点的 key 域 未用 */
- head->next = NULL;
- *list = head;
- return OK;
- }
- int IsEmpty(LLNptr list)
- {
- return list->data.value == 0;
- }
- int ListLength(LLNptr list)
- {
- return list->data.value;
- }
- Status GetRecord(LLNptr list, int i, Record *e)
- {
- /* 取得表list中的第i个元素, 并用e返回 */
- LLNptr p = list->next; /* p 指向第一个记录结点 */
- if (IsEmpty(list)) {
- fprintf(stderr, "Error: list empty!\n");
- return ERROR;
- }
- if (i < 1 || i > ListLength(list)) {
- fprintf(stderr, "Error: position parameter %d out of range!\n", i);
- return ERROR;
- }
- while(--i) p = p->next; /* p 指向第i个元素 */
- *e = p->data;
- return OK;
- }
- Record* PLocateRecord(LLNptr list, Record e, int (*compare)(Record *e1, Record *e2))
- {
- /* 返回表list中与给定元素e满足compare关系的记录指针 */
- LLNptr p = list->next;
- while (p) {
- if (compare(&p->data, &e))
- return &p->data;
- p = p->next;
- }
- return NULL;
- }
- Status ListInsert(LLNptr list, int i, Record e)
- {
- /* 将记录 e 插入表list中的第 i 个位置上 */
- LLNptr s, p = list;
- int j = 0; /* j 作计数器 */
- if (i < 1 || i > ListLength(list)+1) {
- fprintf(stderr, "Error: position parameter %d out of range!\n", i);
- return ERROR;
- }
- while (p && j < i-1) { p = p->next; j++; }
- s = (LLNptr)malloc(sizeof(LLNode));
- if (!s) {
- fprintf(stderr, "Error: fail to allocate memory!\n");
- return ERROR;
- }
- s->data = e; s->next = p->next;
- p->next = s;
- list->data.value++;
- return OK;
- }
- Status ListDelete(LLNptr list, int i, Record *e)
- {
- /* 删除表list中的第i个位置上的记录,并用 e 返回 */
- LLNptr p1 = list;
- LLNptr p2;
- int j = 0; /* j 作计数器 */
- if (IsEmpty(list)) {
- printf("Error: list empty!\n");
- return ERROR;
- }
- if (i < 1 || i > ListLength(list)) {
- printf("Error: invalid index!\n");
- return ERROR;
- }
- while (p1->next && j < i-1) { /* p1 指向第 i-1 个元素 */
- p1 = p1->next;
- j++;
- }
- p2 = p1->next; /* p2 指向第 i 个元素 */
- *e = p2->data;
- p1->next = p2->next;
- free(p2);
- list->data.value--;
- return OK;
- }
- Status ListTraverse(LLNptr list, void (*visit)(Record *e))
- {
- /* 用visit函数遍历表list中的元素有且仅有一次 */
- LLNptr p = list->next;
- if (IsEmpty(list)) {
- printf("list empty!\n");
- return ERROR;
- }
- while (p) {
- visit(&p->data);
- p = p->next;
- }
- return OK;
- }
- Status ListPrint(LLNptr list)
- {
- return ListTraverse(list, printRecord);
- }
- void printRecord(Record *e)
- {
- printf("(%s, %d)\n", e->key, e->value);
- }
- int Equal(Record *e1, Record *e2)
- {
- return strcmp(e1->key,e2->key)==0;
- }
Hashtable.c
- // Hashtable.c
- // 哈希函数的实现
- #include <stdio.h>
- #include "common.h"
- int hash(char* key)
- {
- char *p = key;
- int hash = 17;
- while (*p) {
- hash = hash * 37 + (*p);
- p++;
- }
- printf("key = %s\thash = %d , hash %% %d = %d\n" , key, hash, LEN_OF_TABLE, hash % LEN_OF_TABLE);
- return hash % LEN_OF_TABLE;
- }
- Status InitTable(LLNptr table[])
- {
- int i;
- for (i = 0; i < LEN_OF_TABLE; i++) {
- if (!InitList(&table[i])) {
- return ERROR;
- }
- }
- return OK;
- }
- Status HashInsert(LLNptr table[], Record e)
- {
- int t_index = hash(e.key);
- if (PLocateRecord(table[t_index], e, Equal)) { /* 哈希表中已存在该记录 */
- printf("Record exists, nothing to do.");
- return OK;
- }
- int ins_pos = ListLength(table[t_index]) + 1;
- if (!ListInsert(table[t_index], ins_pos, e)) {
- return ERROR;
- }
- return OK;
- }
- Record* HashSearch(LLNptr table[], Record e)
- {
- int t_index = hash(e.key);
- return PLocateRecord(table[t_index], e, Equal);
- }
- Status HashTraverse(LLNptr table[])
- {
- int i;
- printf("The hash table:\n");
- for (i = 0; i < LEN_OF_TABLE; i++) {
- printf("List[%d]:\n", i);
- ListPrint(table[i]);
- printf("\n");
- }
- return OK;
- }
main.c
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include "common.h"
- char* toString(int i);
- int main()
- {
- printf("Program start up ...\n");
- /* 表长为LEN_OF_TABLE的哈希表,每个元素为一个单链表指针 */
- LLNptr hashtable[LEN_OF_TABLE];
- Record rds[RECORD_NUM];
- Record* pe;
- Record* qe;
- int i;
- if (!InitTable(hashtable)) {
- fprintf(stderr, "Error: fail to initialize the hashtable!\n");
- exit(FAILURE);
- }
- printf("initialize the hashtable successfully!\n");
- HashTraverse(hashtable);
- for (i = 0; i < RECORD_NUM; i++) {
- rds[i].key = toString(i);
- rds[i].value = i;
- printf("Record: (%s %d) \n", rds[i].key, rds[i].value);
- printf("prepare to insert ...");
- if (!HashInsert(hashtable, rds[i])) {
- printf("failed to insert record!");
- }
- }
- HashTraverse(hashtable);
- pe = (Record* ) malloc(sizeof(Record));
- pe->key = "11111";
- qe = HashSearch(hashtable, *pe);
- if (qe != NULL) {
- printRecord(qe);
- }
- else {
- printf("Record Not Found.\n");
- }
- pe->key = "11112";
- qe = HashSearch(hashtable, *pe);
- if (qe != NULL) {
- printRecord(qe);
- }
- else {
- printf("Record Not Found.\n");
- }
- return 0;
- }
- char* toString(int i)
- {
- char *p = (char *)malloc(5*sizeof(char) + 1);
- char *q;
- if (!p) {
- fprintf(stderr, "Error, fail to allocate memory.");
- exit(FAILURE);
- }
- q = p;
- while (q < p+5) {
- *q = i + ' ';
- q++;
- }
- *q = '\0';
- return p;
- }
- 一个哈希表的实现
- 哈希表一个简单的实现
- 关于一个哈希表的实现
- 字符串哈希表的一个实现
- 一个简单的哈希表实现
- 自己写的一个哈希表的实现
- 一个简单的哈希表的实现
- 一个开源的哈希表源码实现
- 一个哈希表的简单实现拉链法
- WMI 的一个实现
- 一个单件基类的实现
- Trie的一个实现
- 有限状态机的一个实现
- 一个链表类的实现
- 一个单链表的实现
- auto_ptr 的一个实现
- WMI 的一个实现
- 一个链表类的实现
- my benchmark
- C#中Split用法~
- 一日一点RakNet(56)--Command Console Server(命令行控制台服务器)
- Android源代码下载及开发环境搭建
- 科技园环球双线机房
- 一个哈希表的实现
- Java数组排序总结(冒泡,选择,插入,希尔)
- 安卓自动化测试执行总结以及疑问-Robotium
- 在TextView控件中使用ImageButton
- 互联网社会化系列之网民的需求分析
- DM642 gel文件和.cmd文件参考
- C/C++在线编译器
- Linux scp 使用详解
- IP机顶盒系列一,WIZNET解决方案