C语言实现的哈希表实现程序

为了巩固一下链表知识,自己实现的一个哈希表,在GCC 4.4.7下编译通过;
hash.h

 代码如下 复制代码

/**
 * Author : maben
 * Date   : 2014-12-23
 */
#ifndef __HASH_H__
#define __HASH_H__
typedef struct _bucket {
    char* key;
    char* value;
    struct _bucket* next;
}Bucket;

typedef struct _hash {
    Bucket* buckets;
}HashTable;

void hash_init(HashTable** hash);
unsigned int get_hash_index(char* str);
int hash_insert(HashTable* hash, char* key, char* value);
int hash_find(HashTable* hash, char* key, Bucket** bucket);
int hash_remove(HashTable* hash, char* key);
void hash_free(HashTable* hash);
#endif
hash.c
/**
 * Author : maben
 * Date   : 2014-12-23
 */

#include "stdio.h"
#include "hash.h"
#include "assert.h"

#define HASH_SIZE 100

void hash_init(HashTable** hash)
{
    (*hash) = (HashTable*)malloc(sizeof(HashTable));
    if ((*hash) == NULL) {
        printf("Hash table initialization failure!\n");
        exit(0);
    }
    (*hash)->buckets = (Bucket*)malloc(sizeof(Bucket) * HASH_SIZE);
    memset((*hash)->buckets, 0, sizeof(Bucket) * HASH_SIZE);
}

unsigned int get_hash_index(char* str)
{
    unsigned int hash = 0;
    unsigned int x = 0;
    while (*str) {
        hash = (hash << 4) + (*str++);
        if ((x = hash & 0xF0000000L) != 0) {
            hash ^= (x >> 24);
            hash &= ~x;
        }
    }
    return (hash & 0x7FFFFFFF) % HASH_SIZE;
}

int hash_insert(HashTable* hash, char* key, char* value)
{
    assert(hash != NULL);
    assert(key != NULL);
    int index = get_hash_index(key);
    Bucket* bucket;
    bucket = &hash->buckets[index];
    while (NULL != (bucket->next)) {
        bucket = bucket->next;
    }
    int key_len = strlen(key);
    int value_len = strlen(value);
    bucket->key = (char*)malloc(sizeof(char) * (key_len + 1));
    bucket->value = (char*)malloc(sizeof(char) * (value_len + 1));
    strcpy(bucket->key, key);
    bucket->key[key_len] = '\0';
    strcpy(bucket->value, value);
    bucket->value[value_len] = '\0';
    bucket->next = (Bucket*)malloc(sizeof(Bucket));
    memset(bucket->next, 0, sizeof(Bucket));
    bucket->next->next = NULL;
    return 0;
}

int hash_find(HashTable* hash, char* key, Bucket** result)
{
    assert(hash != NULL);
    assert(key != NULL);
    int index = get_hash_index(key);
    Bucket* bucket = &hash->buckets[index];
    while (bucket) {
        if (bucket->key && strcmp(key, bucket->key) == 0) {
            (*result) = bucket;
            return 1;
        }
        bucket = bucket->next;
    }
    return 0;
}

int hash_remove(HashTable* hash, char* key)
{
    assert(hash != NULL);
    assert(key != NULL);
    int index = get_hash_index(key);
    Bucket* bucket = &hash->buckets[index];
    int is_sub = 0;
    Bucket* prev = NULL;
    while (bucket) {
        if (strcmp(key, bucket->key) != 0)
            continue;
        if (bucket->key)
            free(bucket->key);
        if (bucket->value)
            free(bucket->value);
        if (is_sub) {
            prev->next = bucket->next;
            free(bucket);
            return 1;
        } else {
            if (bucket->next)
                memcpy(bucket, bucket->next, sizeof(Bucket));
            return 1;
        }
        prev = bucket;
        bucket = bucket->next;
        is_sub++;
    }
    return 0;
}

void hash_free(HashTable* hash)
{
    int i = 0;
    Bucket* bucket;
    for (i = HASH_SIZE - 1; i > -1; i--) {
        bucket = &hash->buckets[i];
        if (!bucket)
            continue;
        int is_sub = 0;
        do {
            if (bucket->key)
                free(bucket->key);
            if (bucket->value)
                free(bucket->value);
            if (is_sub) {
                Bucket* tmp = bucket;
                bucket = bucket->next;
                free(tmp);
            } else {
                bucket = bucket->next;
            }
            is_sub++;
        } while(bucket);
    }
    free(hash->buckets);
    free(hash);
    hash = NULL;
}
用法:
#include "stdio.h"
#include "hash.h"

int main(int argc, char* argv[]) {
    HashTable* hash;
    hash_init(&hash);
    int i = 0;
    for (; i < 200; i++) {
        char key[10] = { 0 };
        char value[10] = { 0 };
        sprintf(key, "hello%d", i);
        sprintf(value, "world%d", i);
        hash_insert(hash, key, value);
    }
    for (i = 0; i < 200; i++) {
        if (i % 2 == 0) {
            char key[10] = { 0 };
            sprintf(key, "hello%d", i);
            hash_remove(hash, key);
        }
    }
    for (i = 0; i < 200; i++) {
        char key[10] = { 0 };
        sprintf(key, "hello%d", i);
        Bucket* bucket;
        int result = hash_find(hash, key, &bucket);
        if (result) {
            printf("%s=>%s\n", bucket->key, bucket->value);
        }
    }
    hash_free(hash);
    return 0;
}

时间: 2024-10-14 22:07:08

C语言实现的哈希表实现程序的相关文章

c语言-C语言学生选课管理 顺序表实现 数据结构课程设计

问题描述 C语言学生选课管理 顺序表实现 数据结构课程设计 学生选课管理系统 用顺序表实现 ◆问题描述 设计一个计算机管理完成的学生选课信息基本业务. ◆要求 课程信息包括:课程编号.课程名称.课程性质.总学时.学分.课程人数上限. 选课信息包括:学号.姓名.选修课程编号.成绩. (1)录入.删除.修改课程信息. (2)录入.删除.修改选课信息. (3)查询.统计选课信息(按学号.学分等): (4)排序. 解决方案 http://wenku.baidu.com/link?url=dKo45dQ7

怎样在部署WinForm项目时修改注册表实现程序安装后开机自动启动?

问题描述 怎样在部署WinForm项目时修改注册表实现程序安装后开机自动启动?请高手们帮忙,多谢了! 解决方案 解决方案二:在注冊表中HKEY_LOCAL_MACHINE/Software/Microsoft/Windows/CurrentVersion/Run或HKEY_CURRENT_USER/Software/Microsoft/Windows/CurrentVersion/Run增加一個值,設置為你的exe路徑即OK解决方案三:是呀!我也是这么想的.可是,每一个客户安装程序的路径都不一样

用哈希表实现图书管理系统

学校Java课的课程实验之一. 用到的数据结构:哈希表 题目要求: 1. 建立的图书类包含如下信息:编号.书名.作者.出版社.出版日期. 2. 能够实现根据以下关键字查询图书:编号.书名.作者.出版社. 3. 能够实现图书信息的录入.删除和修改. 4.录入的图书至少要有10本以上. 5.具有图形用户界面.   功能介绍: 录入.删除.修改图书: 按编号.书名.作者.出版社查询图书.   界面设计: 主界面(会的不多,所以用了最简易的流式布局): 检索模块: 从四个检索字段中选择一种,输入检索词,

代码-C/C++ 用顺序表实现的括号匹配问题

问题描述 C/C++ 用顺序表实现的括号匹配问题 我的代码 #include<stdio.h> #include<string.h> #define TRUE 1 #define FALSE 0 typedef struct { char data[100]; int top; }Stack; int InitStack(Stack stack) { stack.top=-1; return TRUE; } int Push(Stack &stackchar &ch

CSS样式表实现分页效果源代码

CSS样式表实现效果很好的分页效果,在学习编程过程中由于文章内容比较多或者列表内容比较多,我们都需要分页!那么你想不想要一种好的分页效果呢?这个是我认为比较容易使用,同时编程方面也挺容易实现的分页,就是以10页为基础,然后上十页和下十页,因为很少有人有兴趣会去看10页甚至20页以后的内容. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1

Oracle 外部表实现方式整理

基于oracle_datapump的外部表实现过程: 一.创建外部表以及产生dmp文件 1.创建directory,需要有 create any directory权限: CREATE DIRECTORY admin AS '/oracle/admin'; 2.创建外部表: SQL> CREATE  TABLE emp_xt ORGANIZATION EXTERNAL ( TYPE ORACLE_DATAPUMP DEFAULT DIRECTORY admin LOCATION ('emp_xt

DropDownList绑定数据表实现两级联动示例

 这篇文章主要介绍了DropDownList绑定数据表实现两级联动具体实现,需要的朋友可以参考下 场景一:平时我们在DropDownList控件下添加下拉选项时,都会使用它的Item.Add方法,直接在代码下添加.如果我们想添加或修改下拉选项,则必须去修改源代码.如果几个DropDownList控件的下拉选项相同,我们则需要重复添加好多次,后期的维护工作很不方便.    场景二:我们在12306网站买票时,肯定遇到过这么一种情景:我们需要先选定目的地的省份,选完省份后在城市选框中会自动加载该省份

指针-关于c++的队列模板链表实现代码

问题描述 关于c++的队列模板链表实现代码 template class QueueTp { private: struct Node {T item; struct Node * next;}; enum { Q_SIZE = 10 };//默认队列长度 Node * front;//指向队列首个对象的指针 Node * rear;//队列尾部对象的指针 int items;//队列中的对象个数 const int qsize;//队列长度 QueueTp(const QueueTp & q)

python单链表实现代码实例_python

链表的定义:链表(linked list)是由一组被称为结点的数据元素组成的数据结构,每个结点都包含结点本身的信息和指向下一个结点的地址.由于每个结点都包含了可以链接起来的地址信息,所以用一个变量就能够访问整个结点序列.也就是说,结点包含两部分信息:一部分用于存储数据元素的值,称为信息域:另一部分用于存储下一个数据元素地址的指针,称为指针域.链表中的第一个结点的地址存储在一个单独的结点中,称为头结点或首结点.链表中的最后一个结点没有后继元素,其指针域为空. python单链表实现代码: 复制代码