#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h> #define HASH_BUCKET_MAX (1024)
#define HASH_BUCKET_CAPACITY_MAX (256)
#define HASHTABLE_DEBUG
#define TRUE 1
#define FALSE 0 #ifdef HASHTABLE_DEBUG
#define DEBUG(format, ...) printf("[%s] [%d] : "format"\n", __FUNCTION__, __LINE__, __VA_ARGS__)
#else
#define DEBUG(format, ...)
#endif struct hash_bucket {
int capacity; /* 桶的容量 */
void *hkey; /* hashtable的key */
void *hdata; /* hashtable的data */
struct hash_bucket *prev;
struct hash_bucket *next;
struct hash_bucket *tail;
}; struct hash {
uint32_t (*hash_key)(void *);
int (*hash_cmp)(const void *, const void*, int len);
struct hash_bucket* bucket[HASH_BUCKET_MAX];
}; uint32_t string_hash_key(void* str);
int string_hash_cmp(const void* src, const void* dst); static struct hash *g_htable = NULL; void hash_create();
void *hash_lookup(void *key);
int hash_add(void *key, void* data);
int hash_delete(void *key);
void hash_destroy();
void hash_iter_print(); #define bucket_free(bucket) \
free(bucket->hkey); \
free(bucket->hdata); \
free(bucket); \
bucket = NULL; uint32_t string_hash_key(void* str) {
char *tmp = (char *)str;
uint32_t key = ;
while(*tmp)
key = (key * ) ^ (uint32_t)(tmp++); DEBUG("string key : %u, index : %d", key, key%HASH_BUCKET_MAX); return key%HASH_BUCKET_MAX;
} int string_hash_cmp(const void* src, const void* dst, int len) {
if (!src || !dst) {
DEBUG("src addr: %p, dst addr: %p", src, dst);
return -;
}
return strncmp((char *)src, (char *)dst, len);
} void hash_create() {
if (g_htable) {
DEBUG("the default hashtable is already created");
return;
} g_htable = (struct hash *)malloc(sizeof(struct hash));
if (!g_htable) {
DEBUG("memory alloc failed.");
return;
} memset(g_htable, , sizeof(struct hash)); g_htable->hash_key = string_hash_key;
g_htable->hash_cmp = string_hash_cmp; return;
} static void bucket_delete(struct hash_bucket** ptr) {
struct hash_bucket *bucket = *ptr;
struct hash_bucket *tmp; while(bucket) {
tmp = bucket;
bucket = bucket->next;
bucket_free(tmp);
}
} void hash_destroy() {
if (g_htable) {
for(int i=; i<HASH_BUCKET_MAX; i++) {
if (g_htable->bucket[i]) {
bucket_delete(&g_htable->bucket[i]);
}
} free(g_htable);
g_htable = NULL;
}
return;
} #define lru_bucket_move(bucket, head) \
bucket->next = head; \
bucket->prev = NULL; \
bucket->capacity = head->capacity; \
\
head->prev = bucket; \
head->tail = NULL; void *hash_lookup(void *key) {
if (!key) {
DEBUG("input para is NULL\n");
return NULL;
} uint32_t index = g_htable->hash_key(key);
struct hash_bucket* head = g_htable->bucket[index];
struct hash_bucket* bucket = head; while(bucket) {
if ( == g_htable->hash_cmp(key, bucket->hkey, strlen((char*)key))) {
if (head != bucket && bucket != head->tail) {
bucket->prev->next = bucket->next;
bucket->next->prev = bucket->prev;
bucket->tail = head->tail; lru_bucket_move(bucket, head);
} else if (bucket == head->tail && head->capacity>) {
bucket->prev->next = NULL;
bucket->tail = bucket->prev; lru_bucket_move(bucket, head);
}
g_htable->bucket[index] = bucket;
return bucket->hdata;
}
bucket = bucket->next;
}
return NULL;
} int hash_add(void *key, void* data) {
if (!key || !data) {
DEBUG("input para is NULL\n");
return FALSE;
} uint32_t index = g_htable->hash_key(key);
struct hash_bucket* head = g_htable->bucket[index]; if (!head) {
head = (struct hash_bucket*)malloc(sizeof(struct hash_bucket));
if (!head) {
DEBUG("no memory for more hash_bucket\n");
return FALSE;
} memset(head, , sizeof(*head));
head->capacity++; head->hkey = strdup((char *)key);
head->hdata = strdup((char *)data);
head->tail = head;
g_htable->bucket[index] = head;
return TRUE;
} int capacity = head->capacity;
struct hash_bucket *new_bucket =
(struct hash_bucket *)malloc(sizeof(struct hash_bucket)); if (!new_bucket) {
DEBUG("no memory for more hash_bucket\n");
return FALSE;
} if (capacity >= HASH_BUCKET_CAPACITY_MAX) {
struct hash_bucket *tail = head->tail;
head->tail = tail->prev; tail->prev->next = NULL;
bucket_free(tail);
} head->prev = new_bucket;
new_bucket->next = head;
new_bucket->capacity = capacity + ;
new_bucket->tail = head->tail;
head->tail = NULL; head->hkey = strdup((char *)key);
head->hdata = strdup((char *)data); g_htable->bucket[index] = new_bucket; return TRUE;
} int hash_delete(void *key) {
if (!key) {
DEBUG("input para is NULL\n");
return FALSE;
} uint32_t index = g_htable->hash_key(key);
struct hash_bucket* head = g_htable->bucket[index];
struct hash_bucket* bkt = head; while(bkt) {
if ( == g_htable->hash_cmp(key, bkt->hkey, strlen((char*)key))) {
if (head != bkt && bkt != head->tail) {
bkt->prev->next = bkt->next;
bkt->next->prev = bkt->prev; } else if (bkt == head->tail && head->capacity>) {
bkt->prev->next = NULL;
bkt->tail = bkt->prev; } else {
if (bkt->next) {
bkt->next->tail = bkt->tail;
bkt->next->capacity = bkt->capacity;
bkt->next->prev = NULL;
g_htable->bucket[index] = bkt->next;
} else {
g_htable->bucket[index] = NULL;
}
} bucket_free(bkt);
if (g_htable->bucket[index]) {
g_htable->bucket[index]->capacity--;
} return TRUE;
}
bkt = bkt->next;
}
return FALSE;
} static void bucket_print(struct hash_bucket** ptr) {
struct hash_bucket *bkt = *ptr;
struct hash_bucket *tmp; while(bkt) {
printf("key=[%s],data=[%s]\n", (char*)bkt->hkey, (char*)bkt->hdata);
bkt = bkt->next;
}
} void hash_iter_print() {
if (g_htable) {
for(int i=; i<HASH_BUCKET_MAX; i++) {
if (g_htable->bucket[i]) {
bucket_print(&g_htable->bucket[i]);
}
}
}
} int main(int argc, char* argv[]) {
hash_create(); hash_add("first", "danxi");
hash_add("second", "test");
hash_add("three", "sad code");
hash_add("four", "let's go"); hash_iter_print(); char * t1 = (char *)hash_lookup("first");
char * t2 = (char *)hash_lookup("second"); printf("%s %s \n", t1, t2);
printf("%s \n", (char*)hash_lookup("four")); hash_delete("four");
hash_iter_print();
hash_destroy(); return ;
}

c语言实现带LRU机制的哈希表的更多相关文章

  1. C语言自带的快速排序(qsort)函数使用方法

    感觉打快排太慢了,找到了c语言自带的函数.这函数用起来没c++的方便,不过也够了. 函数名称:qsort,在头文件:<stdlib.h>中 不多说,上代码: #include <st ...

  2. C 语言多线程与锁机制

    C 语言多线程与锁机制 多线程 #include <pthread.h> void *TrainModelThread(void *id) { ... pthread_exit(NULL) ...

  3. django自带权限机制

    1. Django权限机制概述 权限机制能够约束用户行为,控制页面的显示内容,也能使API更加安全和灵活:用好权限机制,能让系统更加强大和健壮.因此,基于Django的开发,理清Django权限机制是 ...

  4. Redis的LRU机制(转)

    原文:Redis的LRU机制 在Redis中,如果设置的maxmemory,那就要配置key的回收机制参数maxmemory-policy,默认volatile-lru,参阅Redis作者的原博客:a ...

  5. 【C++】异常简述(一):C语言中的异常处理机制

    人的一生会遇到很多大起大落,尤其是程序员. 程序员写好的程序,论其消亡形式无非三种:无疾而终.自杀.他杀. 当然作为一名程序员,最乐意看到自己写的程序能够无疾而终,因此尽快的学习异常处理机制是非常重要 ...

  6. Java程序语言的后门-反射机制

    在文章JAVA设计模式-动态代理(Proxy)示例及说明和JAVA设计模式-动态代理(Proxy)源码分析都提到了反射这个概念. // 通过反射机制,通知力宏做事情 method.invoke(obj ...

  7. 146. LRU 缓存机制 + 哈希表 + 自定义双向链表

    146. LRU 缓存机制 LeetCode-146 题目描述 题解分析 java代码 package com.walegarrett.interview; /** * @Author WaleGar ...

  8. 浅谈MatrixOne如何用Go语言设计与实现高性能哈希表

    目录 MatrixOne数据库是什么? 哈希表数据结构基础 哈希表基本设计与对性能的影响 碰撞处理 链地址法 开放寻址法 Max load factor Growth factor 空闲桶探测方法 一 ...

  9. 数据结构算法C语言实现(二)---2.3线性表的链式表示和实现之单链表

    一.简述 [暂无] 二.头文件 #ifndef _2_3_part1_H_ #define _2_3_part1_H_ //2_3_part1.h /** author:zhaoyu email:zh ...

随机推荐

  1. 分享一个展示文章列表的CSS样式

    最近在帮朋友处理一个网站前端显示文章列表的时候,其中有个变通的思路,现整理出来留给有需要的朋友参考及自己备忘. 显示效果为:标题左对齐,日期右对齐. 标题和日期中间用常规的原点(“.”) 代替,显示效 ...

  2. Block代替delegate,尽量使用block,对于有大量的delegate方法才考虑使用protocol实现.

    Block代替delegate,尽量使用block,对于有大量的delegate方法才考虑使用protocol实现. 1.Block语法总结及示例如下:         //1.普通代码块方式bloc ...

  3. #leetcode刷题之路1-两数之和

    给定两个整数,被除数 dividend 和除数 divisor.将两数相除,要求不使用乘法.除法和 mod 运算符.返回被除数 dividend 除以除数 divisor 得到的商. 示例 1:输入: ...

  4. ETO的公开赛T1《矿脉开采》题解(正解)(by Zenurik)

    作为T1,当然是越水越好啦qwq 显然经目测可得,那个所谓的质量评级根本就没卵用,可以直接\(W_i = W_i^{V_i}\)累积到利润里面. 这样,本问题显然是一个"子集和"问 ...

  5. <寒假逆向学习第一天> 破解基础知识之介绍常见工具和壳的特征

    对于我们新手来说,程序是什么语言编写的?程序到底有没有加壳?程序加了什么壳?一直在我们心中充满了疑惑,本文我将根据我的近期学习,总结一下常见的工具和壳的特征. 一:程序是什么语言编译的 从目前接触到程 ...

  6. jdbc学习笔记02

    数据库连接池 DBCP DataBase Conection Pool:数据库连接池 如果没有数据库连接池,每一次业务都需要服务器和数据库服务器建立一次连接,业务处理完连接断开,如果有1万次业务处理, ...

  7. linux命令之磁盘和文件系统操作

    1.   fdisk:磁盘分区命令 语法:fdisk [选项][参数] 命令说明:fdisk是linux系统里常用的一种磁盘管理工具,可以创建和管理系统分区 常用命令选项: -l:列出指定的并退出,没 ...

  8. Linux系统修改/etc/sysconfig/i18n文件,桌面无法正常显示

    在Windows环境下使用SSH Secure Shell Client登陆VMware Workstation中Linux系统查询hive表时,中文显示乱码:数字和url显示为NULL,网上说: 1 ...

  9. 继上一篇bootstrap框架(首页)弄的资讯页面

    还是和上一篇首页一样给出每一步的注解: 做的有点简单,但是,以后还是会加深的.毕竟是初学者嘛! <html lang="zh-cn">   <head>   ...

  10. 码云配置webhooks自动触发拉取代码

    webhooks的使用 码云和github的钩子叫webhooks 每次您 push 代码后,都会给远程 HTTP URL 发送一个 POST 请求 码云项目管理页面的webhooks设置: http ...