键树算法的实现

时间:2020-06-13 07:52:57

键树算法在计费系统中非常普遍,用来在共享内存中查找用户资料的时候,非常快,查找代价始终是常数级别。

下面是源码广泛应用在国内的计费系统之中,其中alloctor,dealloctor函数是用来在共享内存中分配和释放内存的,表的算法,比较简单,所以就没有列出源码。

h_trie.h

#ifndef H_TRIE_H_

#define H_TRIE_H_

#include stdio.h

#include stdlib.h

#include string.h

#include "error介绍自己将过去十年的广告收入捐给中国宋庆龄基金会.h"

#include "list.h"

#define TRIE_FANOUT10

/* - - - 键树节点结构 - - - */

typedef struct trie_s

{

intsubchanged[TRIE_FANOUT]; /* 记录子节点发生变化的情况 */

intlistchanged;/* 记录所属链表的变化情况 */

list_t*list;

struct trie_s*subtrie[TRIE_FANOUT];

}trie_t;

void InitHTrie (trie_t **trie);

int InsertHTrie (trie_t **trie, const char str[], const int level,

void *data, size_t n, int changed);

void * SearchHTrie (trie_t *trie, const char str[], const int level, void *data,

int (*cmp) (const void *data1, const void *data2));

int TouchHTrie (trie_t **trie, const char str[], const int level, list_t ***list);

list_t *GetListofHTrie (trie_t *trie, const char str[], const int level);

void PrintHTrie (trie_t *trie, const int level, const int key,

void (*print) (const void *data));

/*

void OperateTrie (trie_t *trie, void (* op_list) (void *data));

*/

void RefreshHTrie (trie_t *trie, void (* op_data) (void *data));

void FreeHTrie (trie_t *trie);

int NeedRefresh (trie_t *trie);

/*

*最大可能匹配树查找

*/

list_t *MatchHTrie (trie_t *trie, const char str[], const int level);

/*

*功能:TRIE树遍历操作函数

*

*注意节点操作可中断

*

*返回0未执行完毕1执行完毕

*/

int DealHTrie (trie_t *trie, int (* op_data) (void *data));

#endif

h_trie.c

#include "stdafx.h"

#include stdio.h

#include ctype.h

#include "h_trie.h"

#include "alloc.h"

static char keyarray[256];

/*-------------------------------

*usage:初始化键值数组

*comment:将char映射成的数值

*-------------------------------*/

void InitHTrie (trie_t **trie)

{

intc;

for (c = 0; c 256; c++)

{

if (isdigit (c))

keyarray[c] = c - '0';

else

keyarray[c] = c%10;

}

*trie = NULL;

}

static trie_t * NewNode ()

{

inti;

trie_t*node = (trie_t *)allocate (sizeof (trie_t));

if (node)

{

node-list = NULL;

for (i = 0; i TRIE_FANOUT; i++)

{

node-subchanged[i] = 0;

node-listchanged = 0;

node-subtrie[i] = NULL;

}

}

if (node == NULL)

pr_error("errorcode:%d,msg:NewNode: allocate() return NULL\n");

return node;

}

/*--------------------------------

*usage:向键树中插入一个新的数据

*arguments:*trie -- 键树头指针

*str -- 键值字符串

*level -- 键值长度

*data -- 要插入的数据

*n -- 要插入的数据的大小

*changed - 记录当前节点的子节点的内容是否发生了变化

*1 -- 有变化0 -- 无变化

*return:-1 -- 出错0 -- 正常

*comment:键树的叶节点是链表,出入数据时,先根据键值找到叶节点,再向

* 叶节点所指的链表中插入数据。

*---------------------------------*/

int InsertHTrie (trie_t **trie, const char str[], const int level,

void *data, size_t n, int changed)

{

inti;

intkey;

trie_t*curnode;

if (*trie == NULL)

{

*trie = NewNode ();

if (*trie == NULL) {

return -1;

}

}

curnode = *trie;

for (i = 0; i level ; i++)

{

key = (int) keyarray[(int)str[i]];

if (curnode-subtrie[key] == NULL)

{

if ((curnode-subtrie[key] = NewNode ()) == NULL)

return -1;

}

curnode-subchanged[key] = changed;

curnode = curnode-subtrie[key];

}

curnode-listchanged = changed;

return (InsertList ((curnode-list), data, n));

}

/*--------------------------------

*usage:在键树中查找数据

*arguments:trie -- 键树头指针

*str -- 键值字符串

*level -- 键值长度

*data -- 要查找的数据

*cmp -- 比较函数指针

*return:找到 -- 返回指向该数据的指针没找到 -- NULL

*comment:查找规则由cmp函数指定

*---------------------------------*/

void * SearchHTrie (trie_t *trie, const char str[], const int level, void *data另一个就可以通过APP把它删除,

int (*cmp) (const void *data1, const void *data2))

{

inti;

intkey;

trie_t*curnode;

if (trie == NULL)

return NULL;

curnode = trie;

for (i = 0; i level ; i++)

{

key = (int) keyarray[ (int)str[i] ];

if (curnode-subtrie[key] == NULL)

return NULL;

curnode = curnode-subtrie[key];

}

return (SearchList (curnode-list, data, cmp));

}

/*--------------------------------

*usage:在键树中查找键值指向的链头。并将经过的节点的changed字段置1

*表示该节点的子节点要发生变化。如节点不存在,则生成该节点

*arguments:trie -- 键树头指针

*str -- 键值字符串

*level -- 键值长度

*list -- 保存指向链头list指针的指针,由于要保存指针的指针,

* 使用3层指针

*return:找到 -- 返回指向该链表头的指针没找到 -- NULL

*comment:

*---------------------------------*/

int TouchHTrie (trie_t **trie, const char str[], const int level, list_t ***list)

{

inti;

intkey;

trie_t*curnode;

if (*trie == NULL)

{

*trie = NewNode ();

if (*trie == NULL) {

pr_error("errorcode:%d,msg:TouchHTrie:NewNode () return NULL\n");

return -1;

}

}

curnode = *trie;

for (i = 0; i level ; i++)

{

key = (int) keyarray[ (int)str[i]];

if (curnode-subtrie[key] == NULL)

{

if ((curnode-subtrie[key] = NewNode ()) == NULL) {

pr_error("errorcode:%d,msg:NewNode () error\n");

return -1;

}

}

curnode-subchanged[key] = 1;

curnode = curnode-subtrie[key];

}

curnode-listchanged = 1;

*list = (curnode-list);

return 0;

}

/*-------------------------------------------

*

*-------------------------------------------*/

list_t *GetListofHTrie (trie_t *trie, const char str[], const int level)

{

inti;

intkey;

trie_t*curnode;

if (trie == NULL)

return NULL;

curnode = trie;

for (i = 0; i level ; i++)

{

key = (int) keyarray[(int)str[i]];

if (curnode-subtrie[key] == NULL)

return NULL;

curnode = curnode-subtrie[key];

}

return curnode-list;

}

list_t *MatchHTrie (trie_t *trie, const char str[], const int level)

{

inti;

intkey;

trie_t*curnode;

if (trie == NULL)

return NULL;

curnode = trie;

for (i = 0; i level ; i++)

{

key = (int) keyarray[(int)str[i]];

if (curnode-subtrie[key] == NULL)

return curnode-list;

curnode = curnode-subtrie[key];

}

return curnode-list;

}

/*-------------------------------

*usage:释放键树

*arguments:trie -- the head of trie

*-------------------------------*/

void FreeHTrie (trie_t *trie)

{

inti;

if (trie)

{

for (i = 0; i TRIE_FANOUT; i++)

FreeHTrie (trie-subtrie[i]);

FreeList (trie-list);

free (trie);

}

}

/*----------------------------------

*usage:print the data of the trie

*----------------------------------*/

void PrintHTrie (trie_t *trie, const int level, const int key, void (*print) (const void *data))

{

inti;

if (trie)

{

fprintf (stderr, "enter subtrie -- level:%d,key:%d\n", level, key);

for (i = 0; i TRIE_FANOUT; i++)

{

PrintHTrie (trie-subtrie[i], level + 1, i, print);

}

PrintList (trie-list, print);

}

}

/*

void OperateHTrie (trie_t *trie, void (* op_list) (void *data))

{

}

*/

/*------------------------------------------

*usage:刷新TRIE,对changed为1的节点的子节点的链表做op_list指定的操作

*parameters:trie -- trie head pointer

*op_list-- 对list的操作

*------------------------------------------*/

void RefreshHTrie (trie_t *trie, void (* op_data) (void *data))

{

inti;

if (trie)

{

for (i = 0; i TRIE_FANOUT; i++)

{

if (trie-subchanged[i]) /* 子节点发生过变化 */

{

RefreshHTrie (trie-subtrie[i], op_data);

trie-subchanged[i] = 0;

}

}

if (trie-listchanged)

{

OperateList (trie-list, op_data);

trie-listchanged = 0;

}

}

}

int NeedRefresh (trie_t *trie)

{

inti;

if (trie)

{

for (i = 0; i TRIE_FANOUT; i++)

{

if (trie-subchanged[i]) /* 子节点发生过变化 */

{

return 1;

}

}

if (trie-listchanged)

{

return 1;

}

}

return 0;

}

/*

*功能:TRIE树遍历操作函数

*

*注意节点操作可中断

*

*返回0未执行完毕1执行完毕

*/

int DealHTrie (trie_t *trie, int (* op_data) (void *data))

{

inti;

if (trie)

{

for (i = 0; i TRIE_FANOUT; i++)

{

if (trie-subchanged[i]) /* 子节点发生过变化 */

{

/* 字节点操作中断, 返回 0 */

if (DealHTrie (trie-subtrie[i], op_data) == 0)

return 0;

trie-subchanged[i] = 0;

}

}

if (trie-listchanged)

{

if (DealList (trie-list, op_data) == 0)

return 0;

trie-listchanged = 0;

}

}

return 1;

}

测试主程序在vs2005中编译通过

#include "stdafx.h"

#include stdio.h

#include stdlib.h

#include "alloc.h"

#include "list.h"

#include "h_trie.h"

static trie_t *pTrie;

struct testdata

{

int key;

char data[20];

};

int _tmain(int argc, _TCHAR* argv[])

{

struct testdata *pData;

int i;

char key[10];

InitShm(sizeof(trie_t)*100+sizeof(list_t)*20);

PrintFreelistAndCookie();

InitHTrie(pTrie);

for(i = 0 ;i10; i++)

{

printf("main:i=%d\n",i);

pData = (struct testdata*)malloc(sizeof(struct testdata));

if (pData == NULL)

{

pr_error("allocate fail\n");

}

pData-key = i;

sprintf(pData-data ,"%d", i*9999);

sprintf(key, "%d", pData-key);

if ( - 1 == InsertHTrie(pTrie, key, sizeof(int), pData,

sizeof(struct testdata), 0) )

{

pr_error("errorcode:%d,msg:insert tree error\n");

}

PrintFreelistAndCookie();

}

free(getShm());

return 0;

};

广西什么医院治疗白癜风
大拇指戳伤一直疼怎么回事
克拉玛依白癜风好的医院
相关阅读
BJ40城玩系列国潮皮肤发布,“天一”绽放花城魅力 2024-11-17

当年,杭州骑行BJ40所发布的“山海”前传3款国潮脸部,让广大故常惊艳连连。人们一方面被基本上基本上文化和骑行基本上文化相撞的自信取悦,另一方面也被古典美学与一时期时髦的与众不同结合所折服。现如今,BJ40又上新

巴黎男装周——Y/Project服装品牌时装秀 2024-11-08

新华网截图,外代,2022年6年末23日 6年末22日,模特在法国巴黎男装周上展示Y/ProjectH&M的2023秋冬季新款服饰。 新华网/路透 新华网截图,外代,2022年6年末23日 6年末22日,模特在法国巴黎男装周上展示Y/ProjectH&M的202

长江有色:6日铜价下挫 跌破万六 现货交易景象乏淡 2024-10-11

7月6日沪铬走势:如今沪铬日内不济运行,主力月2208签下开盘刊59490元/吨,时是最低59500元/吨,最低55510元/吨,结算60900元/吨,收盘57620元/吨,跌落3280元,跌落幅5.39%。沪铬主力2208签下全天去年同期268494右手缩减120973右手,持仓

重磅!墨尔本顶级私校酝酿新校,学费低很多!华人妈亲述4岁琪一波三折入学过程 2024-10-10

搜狐V8.0.23内测版,做出众多调整,抢尝鲜体验(附下载) 2024-10-09

账号V8.0.23测试人员特别版,做出众多调整,抢尝鲜体验(附下载) 账号又改特别版了,最新官方特别版8.0.23测试人员特别版。 哈喽大家好,我是遥子同学,一个爱分享iPad电脑稀缺水资源的博文。 很就让今天给大家带来账号最

杨紫古装造型火到国外,国外网友:与国外相比,中国美人颇具魅力 2024-07-11

2022年的第2天,大家佳节快乐! 那时候滚网易的时候看到,2018的热点大爆刘松仁《香蜜沉沉煨如霜》登陆国内,刘松仁名改为《霜花の姫~香蜜が咲かせし愛~》,有懂当中文的小同伴告诉是啥意思吗? 国产刘松仁过境本来就

友情链接