最近在弄linux下弄一个与哈希表有关的东西,然后找到了uthhash这个东西,自己有看过别人介绍的博客,还有例子,但是例子不够详细,很多东西自己试过才知道,
下边把我的源码发上来,上边也有一些注释,写的不是很好,是个半成品。
#include "uthash.h"
#include
#include
#include
#include
//哈希表的实质就是把key和内存地址通过哈希函数关联起来,从而节省时间。
typedef struct net_kit{
char key[50];
time_t t1;//获取当前时间距离1970.1.1的秒数。
char content[32];//32位的一个东西
UT_hash_handle hh; /* makes this structure hashable */
}Net_Kit;
//定义哈希表指针
Net_Kit *users = NULL;
int insert(char *tuple4,char *con);
Net_Kit * search(char *tuple4);
int32_t update(char *tuple4,char*con);
time_t timeinfo();
void changed(Net_Kit *new_kit);
//定义那3个函数
int insert(char *tuple4,char *con)
{
Net_Kit *tmp_kit = NULL;
Net_Kit *lastkit = NULL;
unsigned int num;
num = HASH_COUNT(users);
// printf("before insert total num is %d\n",num);
if(num !=0)
{
//先查找这个tuple4是不是已经存在了,num 为0查找会出现错误。
//HASH_FIND_STR(users, tuple4, tmp_kit );
}
if(tmp_kit==NULL)//就说明原来没有,第一次出现
{
//判断有没有满,满了的话先删除一个好久没用的
if(num>=100000000)
{
lastkit = users;
//必须得先确定唯一得端口才能来删除
//直接从users头找找到最后边的东西,然后删除掉
while(lastkit->hh.next){
lastkit = lastkit->hh.next;
}
HASH_DEL( users, lastkit); /* user: pointer to deletee */
free(lastkit);
}
//然后申请内存
tmp_kit = (Net_Kit*)malloc(sizeof(Net_Kit));
if(tmp_kit == NULL)//分配失败
{
printf("malloc failed");
return 0;
}
tmp_kit->t1 = timeinfo();
strcpy(tmp_kit->key,tuple4);
strcpy(tmp_kit->content,con);
HASH_ADD_STR( users, key, tmp_kit ); //这个key是键值
}else{
printf("this tuple4 has exited!\n");
return 0;
}
//插入成功返回1,不成功返回0;
return 1;
}
int32_t update(char *tuple4,char*con)
{
//先查找,然后再修改
Net_Kit* tmp_kit = NULL;
HASH_FIND_STR(users, tuple4, tmp_kit );
if(tmp_kit !=NULL)//找到了
{
//需要更新时间???
tmp_kit->t1 = timeinfo();
strcpy(tmp_kit->content,con);
changed( tmp_kit);//更新顺序
return 1;
}
return 0;
}
Net_Kit * search(char *tuple4)
{
printf("search begin\n");
Net_Kit* tmp_kit = NULL;
Net_Kit* next_kit = NULL;
HASH_FIND_STR(users, tuple4, tmp_kit );//这个是从头开始查,如果由一样掉,先返回第一个。
if(tmp_kit !=NULL)
{
//这儿写些东西用来测试
if(tmp_kit->hh.next){
next_kit = tmp_kit->hh.next;
printf("更新前他的后一个包键值为%s",next_kit->key);
printf("更新前他的后一个东西的包内容");
puts(next_kit->content);
}
if(tmp_kit->hh.prev){
next_kit = tmp_kit->hh.prev;
printf("更新前他的前一个包键值为%s",next_kit->key);
printf("更新前他的前一个东西的包内容");
puts(next_kit->content);
}
//需要更新时间???
tmp_kit->t1 = timeinfo();
changed( tmp_kit);//更新顺序
return tmp_kit;
}
else
return NULL;
}
time_t timeinfo()
{
// time(&tmp_time)函数获取当前时间距1970年1月1日的秒数,以秒计数单位,存于rawtime 中。
time_t tmp_time;
time(&tmp_time);
return tmp_time;
}
//这个函数就是弄他的前一个还有后一个指向的东西
void changed(Net_Kit *new_kit)
{
Net_Kit *temp_prekit;
Net_Kit *temp_nextkit;
Net_Kit *firstkit;
temp_prekit = new_kit->hh.prev;
temp_nextkit = new_kit->hh.next;
if(temp_prekit)//他前一个不为空
{
firstkit = temp_prekit;
while(firstkit->hh.prev)//获取第一个
{
firstkit = firstkit->hh.prev;
}
if(temp_nextkit)//后一个也不为空
{
temp_prekit->hh.next=temp_nextkit;//他前一个的后一个指向他的后一个
temp_nextkit->hh.prev= temp_prekit;
//
new_kit->hh.prev = NULL;//他的前一个指向空,后一个指向第一个
new_kit->hh.next = firstkit;
//第一个的前一个由空指向他
firstkit->hh.prev = new_kit;
}else{
temp_prekit->hh.next = NULL;//他的前一个的next指向空
new_kit->hh.prev = NULL;//他的前一个指向空,后一个指向第一个
new_kit->hh.next = firstkit;
//第一个的前一个由空指向他
firstkit->hh.prev = new_kit;
}
}/*else{
if(temp_nextkit)//后一个不为空
{
//那他就是最新一个不用改变
}else
{
//说明只有他一个,那也不需要改变
}
}*/
}
int main(int argc,char *argv[])
{
char in[10];
char tuple4[50];
char con[500];
int32_t run = 1;
int32_t times ;
Net_Kit *temp_kit = NULL;
while(run)
{
printf(" 1.insert\n");
printf(" 2.update\n");
printf(" 3.search\n");
printf(" 4.exit\n");
printf(" 5.sort by time and put out\n");
printf(" 6.insert many data");
fgets(in,10,stdin);
//gets(in);
switch(atoi(in))
{
case 1:
printf("--insert--\n");
printf("tuple is?");
fgets(tuple4,50,stdin);//他会把换行符也会读进去。
//这儿可以加上一些长度检验什么读。
printf("kit is?");
fgets(con,500,stdin);
//if(insert("1","2")==1)
//printf("insert success\n");
if( insert(tuple4,con)==1)
printf("insert success\n");
else
printf("insert falied\n");
break;
case 2:
printf("-----update-----\n");
printf("tuple is?");
fgets(tuple4,50,stdin);
printf("kit is?");
fgets(con,500,stdin);
if( update(tuple4,con))
printf("update success\n");
else
printf("update falied\n");
break;
case 3:
printf("-----search------ \n");
temp_kit = NULL;
printf("tuple is?");
fgets(tuple4,50,stdin);
temp_kit = search(tuple4);
if( temp_kit !=NULL)
{
puts(temp_kit->content);
}
else
printf("no this kit\n");
break;
case 4:
run = 0;
break;
case 5:
while( users->hh.prev)//先给users指向最前边的东西
{
users = users->hh.prev;
}
temp_kit = users;
while(temp_kit !=NULL)
{
printf("key:%s,con:%s",temp_kit->key,temp_kit->content);
temp_kit = temp_kit->hh.next;
// puts(users->hh.next);
}
break;
case 6:
times= 10000000;
char a[50];
char b[100];
strcpy(a,"172.16.18.235,500,111.11.11.111,400");
strcpy(b," How are you ? I'm fine,and you ? I'm OK ,thankyou!");
while(times != 0)
{
insert(tuple4,con);
times--;
}
break;
default:
printf("input error\n");
break;
}
}
return 0;
}
下边说下uthash这个东西,你从相应的.h文件里边可以看到他不是单纯的哈希表,结构体里边还有两个双向指针,可以指向他的前一个和后一个,
在插入的时候我测试过他是有顺序的,从头到尾像是一个双向链表一样,然后键值里边的东西是可以相同的,如果你查找的话他是会按照从头到后返回第一次出现到那个。
我这个例子里边每次查找和更新的时候会把正在弄的这个结点放到头上,把他的前一个和后一个链接起来,如果存在的话。
说了这些,其实都是我自己试验的结果,他里边的代码我也不是很懂,大家凑合的看把。