TrieTree(字典树,前缀树) 的实现 (增删改查)

以下 代码 vs2012 下多线程 海量数据  测试过 无内存泄漏


// TrieTreeTest.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include "trie.h"
#include <windows.h> 
#include <ctime>  
#include "vld.h"

#include "ieee_addr.h"


#define MULTY_THREADS 1


int g_keep_run = 1;
TrieRoot root = {0};


char * create_a_ieee()
{
#if 1
	char * text = NULL;

	text = (char *)malloc (17);

	for(int i = 0; i < 16;i++)
	{
		int index = rand() % 16;
		_snprintf(text + i,1,"%x",index);
	}
	text[16] = 0;
	if(strlen(text)!= 16)
	{
		printf("fuck error\n");
	}
	return text;
#else
	int index = rand() %  (sizeof(text) / sizeof(char *));
	return text[index];
#endif
	
}

char * create_a_string(char * ieee)
{
	char * text;

	text = (char *)malloc(21);

	strcpy(text,ieee);
	text[16] = 0;
	return text;
}


void printf_handler(void * data)
{
	printf("%s\n",data);
}

void free_handler(void * data)
{
	free(data);
}

DWORD WINAPI add(LPVOID pM)  
{
	char * ieee;
	char * str;
	
	while(g_keep_run)
	{
		int time_s = rand() % 2;
		
		ieee = create_a_ieee();
		str = create_a_string(ieee);

		if(TRIE_SUCCESS == trie_insert(&root,ieee,str))
		{
		  //printf("add [%s]\n",key[index]);
		}
		else
		{
			free(str);
		}
		free(ieee);
		Sleep(time_s);
	}

    return 0;  
}

DWORD WINAPI upd(LPVOID pM)  
{
	char * ieee;
	char * str;
	char * old_str;
	while(g_keep_run)
	{

		int time_s = rand() % 2;
		ieee = create_a_ieee();
		str = create_a_string(ieee);

		if(TRIE_SUCCESS == trie_update(&root,ieee,str,(void **)&old_str))
		{
			free(old_str);
		}
		else
		{
			free(str);
		}
		free(ieee);
		Sleep(time_s);
	}

    return 0;  
}

DWORD WINAPI sch(LPVOID pM)  
{  
	char * ieee;

	while(g_keep_run)
	{
		int time_s = rand() % 100;
		ieee = create_a_ieee();

		char * data = NULL;
		trie_search(&root,ieee,(void **)&data);
		free(ieee);
		Sleep(time_s);
	}

    return 0;  
}

DWORD WINAPI del(LPVOID pM)  
{  
	char * ieee;
    char * data_pointer;

	while(g_keep_run)
	{
		int time_s = rand() % 100;
		ieee = create_a_ieee();

		if(TRIE_SUCCESS == trie_delete(&root,ieee,(void **)&data_pointer))
		{
			free(data_pointer);
		}
		//else
			//printf("del [%s] failed\n",key[index]);
		free(ieee);
		Sleep(time_s);
	}

    return 0;  
}

DWORD WINAPI fore(LPVOID pM)  
{  
	while(g_keep_run)
	{
		srand( (unsigned)time(NULL ) );//srand()函数产生一个以当前时间开始的随机种子.应该放在for等循环语句前面 不然要很长时间等待  
		int index = rand() % 8;

		trie_foreach(&root,printf_handler);
		Sleep(index);
	}

    return 0;  
}

int _tmain(int argc, _TCHAR* argv[])
{
	int cha;
	int count = 20;
	void * data_pointer;
	srand( (unsigned)time(NULL ) );

	
	trie_init(&root);

#if 1
	HANDLE add_handle = CreateThread(NULL, 0, add, NULL, 0, NULL);  
	HANDLE sch_handle = CreateThread(NULL, 0, sch, NULL, 0, NULL);  
	HANDLE upd_handle = CreateThread(NULL, 0, upd, NULL, 0, NULL);  
	HANDLE del_handle = CreateThread(NULL, 0, del, NULL, 0, NULL);  
//	HANDLE	for_handle = CreateThread(NULL, 0, fore, NULL, 0, NULL); 
	
	cha = getchar();
	g_keep_run = 0;
	
	WaitForSingleObject(add_handle, INFINITE);  
	WaitForSingleObject(sch_handle, INFINITE);  
	WaitForSingleObject(upd_handle, INFINITE);  
	WaitForSingleObject(del_handle, INFINITE);  
//	WaitForSingleObject(for_handle, INFINITE);  

	CloseHandle(add_handle);
	CloseHandle(sch_handle);
	CloseHandle(upd_handle);
	CloseHandle(del_handle);
//	CloseHandle(for_handle);


//	for(int i =0;i<key_size;i++)
//			trie_delete(&root,key[i],(void **)&data_pointer);
	
	trie_foreach(&root,free_handler);

	trie_destroy(&root);
	 
//	getchar();
#else
	char * str1 = (char *) malloc(21);
	char * str2 = (char *) malloc(21);

	char * strout;

	sprintf(str1,"fuckyou");
	sprintf(str2,"fuckme");


	trie_insert(&root,"123456789",str1);
	trie_insert(&root,"123123123",str1);
	trie_insert(&root,"123123123",str1);
	trie_insert(&root,"123123123",str1);
	trie_insert(&root,"123123123",str1);

	trie_search(&root,"123456789",(void **)&strout);


	//trie_update(&root,"123456789",(void *)str2,(void **)&strout);
	//free(strout);

	if(TRIE_SUCCESS == trie_delete(&root,"123123123",(void **)&strout))
	{
		//free(strout);
	}
	if(TRIE_SUCCESS == trie_delete(&root,"123123123",(void **)&strout))
	{
		//free(strout);
	}

	free(str1);
	free(str2);

	trie_destroy(&root);
#endif
	return 0;
}


<pre class="cpp" name="code">// *****************************************************************************
// * trie.h
// *
// * an implementation of a trie tree
// *
// * author: zison sun
// *
// * date: 2016-8-16
// *****************************************************************************

#ifndef	_MACRO_trie_DATA_STRUCTURE_HEADER_
#define	_MACRO_trie_DATA_STRUCTURE_HEADER_

#define WINDOWS 1

#if WINDOWS
#include <windows.h>
#else
#include <pthread.h>
#endif

#define TRIE_SON_NUM	16		//(0-F)

enum trieStatus
{
	TRIE_ERROR	=	0,
	TRIE_SUCCESS = 	1,
};

typedef struct tagTrie
{
	int		href; //引用计数
	void * 	data_pointer; //数据指针
	void *  addr_in_parent; //自身在父节点中的地址
	struct tagTrie * branch[TRIE_SON_NUM];
} Trie, * PTrie;

typedef struct tagTrieRoot
{
#if WINDOWS
	HANDLE hMutex;
#else
	pthread_rwlock_t trie_lock;
#endif

	Trie * proot;
} TrieRoot, * PTrieRoot;

typedef void (*trieCallback)(void *);

trieStatus trie_init(PTrieRoot ptrie_root);

trieStatus trie_insert(PTrieRoot ptrie_root,char * word,void * data_pointer);
trieStatus trie_update(PTrieRoot ptrie_root,char * word,void * data_pointer,void ** old_data_pointer);
trieStatus trie_search(PTrieRoot ptrie_root,char * word,void ** data_pointer);
trieStatus trie_delete(PTrieRoot ptrie_root,char * word,void ** data_pointer);
trieStatus trie_foreach(PTrieRoot ptrie_root,trieCallback  call);
trieStatus trie_destroy(PTrieRoot ptrie_root);

#endif //_MACRO_trie_DATA_STRUCTURE_HEADER_


 

// *****************************************************************************
// * trie.c
// *
// * an implementation of a trie tree
// *
// * author: zison sun
// *
// * date: 2016-8-16
// *****************************************************************************
#include "stdafx.h"
#include "vld.h"

#include <stdlib.h>
#include <string.h>

#include "trie.h"

void _trie_rwlock_rdlock(PTrieRoot ptrie_root);
void _trie_rwlock_wrlock(PTrieRoot ptrie_root);
void _trie_rwlock_unlock(PTrieRoot ptrie_root);

trieStatus _trie_delete(PTrie * pptrie,char * word,void ** data_pointer);
void _trie_foreach(PTrie ptrie,trieCallback  call);
void _trie_destroy(PTrie * pptrie);

void _trie_rwlock_rdlock(PTrieRoot ptrie_root)
{
#if WINDOWS
	DWORD dReturn = WaitForSingleObject(ptrie_root->hMutex,INFINITE);
#else

#endif
}

void _trie_rwlock_wrlock(PTrieRoot ptrie_root)
{
#if WINDOWS
	DWORD dReturn = WaitForSingleObject(ptrie_root->hMutex,INFINITE);
#else

#endif
}

void _trie_rwlock_unlock(PTrieRoot ptrie_root)
{
#if WINDOWS
	ReleaseMutex(ptrie_root->hMutex);
#else

#endif
}

int trie_char_to_index(char charsert)
{
	if(charsert >= '0'  && charsert <= '9' )
		return (charsert - '0');
	else if(charsert >= 'A'  && charsert <= 'F' )
		return (charsert - 'A' + 10);	
	else if(charsert >= 'a'  && charsert <= 'f' )
		return (charsert - 'a' + 10);
	else
		return -1;
}

trieStatus trie_word_check(char * word)
{
	while(*word)
	{
		if(-1 == trie_char_to_index(*word))
			return TRIE_ERROR;

		word++;
	}

	return TRIE_SUCCESS;
}

PTrie trie_malloc()
{
	PTrie  ptrie_temp;
	
	ptrie_temp  = (PTrie) malloc(sizeof(Trie));
	if(!ptrie_temp)
	{
		return 0;
	}
	memset(ptrie_temp,0,sizeof(Trie));

	return ptrie_temp;
}

void trie_free(PTrie ptrie)
{
	if(!ptrie)
		return;
	
	//设置父节点中自己的那个索引为NULL
	if(ptrie->addr_in_parent)
		*((int *)ptrie->addr_in_parent) = NULL;
	free(ptrie);
	
	return ;
}

trieStatus trie_init(PTrieRoot ptrie_root)
{
#if WINDOWS
	ptrie_root->hMutex = CreateMutex(NULL,FALSE,NULL);
#else

#endif
	return TRIE_SUCCESS;
}
/*
 *   warning: chareset in	word  should in [0-9][a-f]
 */
trieStatus trie_insert(PTrieRoot ptrie_root,char * word,void * data_pointer)
{
	int index = -1;
	PTrie ptrie_cur;
	PTrie ptrie_new;
	trieStatus ret = TRIE_ERROR;
	void * data_p;

	if(TRIE_ERROR == trie_word_check(word))
		return TRIE_ERROR;

	if(!ptrie_root)
		return TRIE_ERROR;

	if(TRIE_SUCCESS == trie_search(ptrie_root,word,&data_p))
		return TRIE_ERROR;

	_trie_rwlock_wrlock(ptrie_root);

#if 1//debug
	char sss_copy[256];
	strncpy_s(sss_copy,word,255);
#endif

	printf("add [%s] begin text=[%s]\n",word,data_pointer);
	if(! ptrie_root->proot)
	{
		ptrie_root->proot = trie_malloc();
	}

	ptrie_cur = ptrie_root->proot;

	while(*word)
	{
		index = trie_char_to_index(*word);
		if(-1 == index)
			goto OnReturn;

		ptrie_cur->href++;

		if(ptrie_cur->branch[index] == NULL)
		{
			ptrie_new = trie_malloc();
			ptrie_cur->branch[index] = ptrie_new;
			ptrie_new->addr_in_parent = &ptrie_cur->branch[index];
		}
		
		ptrie_cur = ptrie_cur->branch[index];
	
		word++;
	}

	ptrie_cur->data_pointer = data_pointer;
	ret = TRIE_SUCCESS;

OnReturn:
	printf("add [%s] end\n",sss_copy);
	_trie_rwlock_unlock(ptrie_root);
	return ret;
}

trieStatus trie_if_exist(PTrieRoot prtie_root,char * word)
{
	void * data_addr;
	
	return trie_search(prtie_root,word,&data_addr);
}

trieStatus trie_update(PTrieRoot ptrie_root,char * word,void * data_pointer,void ** old_data_pointer)
{
	int index = -1;
	PTrie ptrie_temp;
	trieStatus ret = TRIE_ERROR;

	if(TRIE_ERROR == trie_word_check(word))
		return TRIE_ERROR;

	if(!ptrie_root)
		return TRIE_ERROR;

	_trie_rwlock_wrlock(ptrie_root);

#if 1//debug
	char sss_copy[256];
	strncpy_s(sss_copy,word,255);
#endif
	if(!ptrie_root->proot)
	{
		_trie_rwlock_unlock(ptrie_root);
		return TRIE_ERROR;
	}	
	
	printf("update [%s] begin text = [%s]\n",word,data_pointer);
	ptrie_temp = ptrie_root->proot;

	while(*word)
	{
		index = trie_char_to_index(*word);
		if(-1 == index)
			goto OnReturn;

		if(ptrie_temp->branch[index] == NULL)
		{
			goto OnReturn;
		}
		
		word++;
		ptrie_temp = ptrie_temp->branch[index];
	}

	*old_data_pointer = ptrie_temp->data_pointer;
	ptrie_temp->data_pointer = data_pointer;
	ret = TRIE_SUCCESS;
OnReturn:
	printf("update [%s] end\n",sss_copy);
	_trie_rwlock_unlock(ptrie_root);
	return ret;

}

trieStatus trie_search(PTrieRoot ptrie_root,char * word,void ** data_pointer)
{
	int index = -1;
	PTrie ptrie_temp;
	trieStatus ret = TRIE_ERROR;

	if(TRIE_ERROR == trie_word_check(word))
		return TRIE_ERROR;

	if(!ptrie_root)
		return TRIE_ERROR;

	_trie_rwlock_rdlock(ptrie_root);

#if 1//debug
	char sss_copy[256];
	strncpy_s(sss_copy,word,255);
#endif
	if(!ptrie_root->proot)
	{
		_trie_rwlock_unlock(ptrie_root);
		return TRIE_ERROR;
	}	
	
	printf("search [%s] begin\n",word);
	ptrie_temp = ptrie_root->proot;

	while(*word)
	{
		index = trie_char_to_index(*word);
		if(-1 == index)
			goto OnReturn;

		if(ptrie_temp->branch[index] == NULL)
		{
			goto OnReturn;
		}
		
		word++;
		ptrie_temp = ptrie_temp->branch[index];
	}

	*data_pointer = ptrie_temp->data_pointer ;
	ret = TRIE_SUCCESS;
OnReturn:
	printf("search [%s] end\n",sss_copy);
	_trie_rwlock_unlock(ptrie_root);
	return ret;

}

trieStatus trie_delete(PTrieRoot ptrie_root,char * word,void ** data_pointer)
{
#if 1
	int index = -1;
	PTrie ptrie_cur;
	PTrie ptrie_cpy;
	int broot = 1;
	trieStatus ret = TRIE_ERROR;

	*data_pointer = NULL;

	if(!ptrie_root)
		return TRIE_ERROR;

	if(TRIE_ERROR == trie_word_check(word))
		return TRIE_ERROR;

	if(TRIE_ERROR == trie_search(ptrie_root,word,data_pointer))
		return TRIE_ERROR;

	_trie_rwlock_wrlock(ptrie_root);
#if 1//debug
	char sss_copy[256];
	strncpy_s(sss_copy,word,255);
#endif
	printf("del [%s] begin\n",word);
	if(! ptrie_root->proot)
		goto onReturn;

	ptrie_cur = ptrie_root->proot;

	while(ptrie_cur && *word)
	{
		index = trie_char_to_index(*word);
		if(-1 == index)
			goto onReturn;

		if(ptrie_cur->branch[index] == NULL)
			goto onReturn;
		 
		ptrie_cpy = ptrie_cur->branch[index];

		if(ptrie_cur->href > 1)
		{
			ptrie_cur->href--;
			broot = 0;
		}
		else
		{
			ptrie_cur->href = 0;
			if(broot)
			{
				ptrie_root->proot = NULL;
				broot = 0;
			}

			trie_free(ptrie_cur);
			ptrie_cpy->addr_in_parent = NULL;
		}

		ptrie_cur = ptrie_cpy;
		word++;
	}


	*data_pointer = ptrie_cur->data_pointer ;
	printf("%s\n",*data_pointer);
	ret = TRIE_SUCCESS;
	if(ptrie_cur->href == 0)
		trie_free(ptrie_cur);

onReturn:
	printf("del [%s] end\n",sss_copy);
	_trie_rwlock_unlock(ptrie_root);

	return ret;
#else
// 递归
	trieStatus ret;
	
	if(!ptrie_root)
		return TRIE_ERROR;
	
	if(TRIE_ERROR == trie_word_check(word))
		return TRIE_ERROR;
	
	printf("delete begin\n");
	_trie_rwlock_wrlock(ptrie_root);
	ret = _trie_delete(&ptrie_root->proot,word,data_pointer);
	printf("delete end\n");
	_trie_rwlock_unlock(ptrie_root);
	return ret;

#endif
}

trieStatus _trie_delete(PTrie *pptrie,char * word,void ** data_pointer)
{
	int index;
	
	if(!*pptrie)
		return TRIE_ERROR;

	if(*word)
	{
		index = trie_char_to_index(*word);
		if(-1 == index)
			return TRIE_ERROR;

		if((*pptrie)->branch[index] == NULL)
		{
			return TRIE_ERROR;
		}
		
		word++;
		if(TRIE_SUCCESS == _trie_delete(&(*pptrie)->branch[index],word,data_pointer))
		{
			(*pptrie)->href--;

			if( (*pptrie)->href ==0)
			{
				trie_free(*pptrie);
				*pptrie = NULL;
			}
		}
	}
	else
	{
		if( (*pptrie)->href ==0)
		{
			*data_pointer = (*pptrie)->data_pointer ;
			trie_free(*pptrie);
			*pptrie = NULL;
		}
	}
	
	return TRIE_SUCCESS;
}


trieStatus trie_foreach(PTrieRoot ptrie_root,trieCallback  call)
{
	if(!ptrie_root)
		return TRIE_ERROR;

	_trie_rwlock_rdlock(ptrie_root);
	printf("foreach begin\n");
	_trie_foreach(ptrie_root->proot,call);
	printf("foreach end\n");
	_trie_rwlock_unlock(ptrie_root);
	return TRIE_SUCCESS;
}


void _trie_foreach(PTrie ptrie,trieCallback  call)
{
	int i = 0;

	if(!ptrie)
		return;
	
	if(0 == ptrie->href && NULL != ptrie->data_pointer)
	{
		call(ptrie->data_pointer);
		return ;
	}
	for(i = 0; i < TRIE_SON_NUM;i++)
	{
		if((ptrie)->branch[i])
		{
			_trie_foreach(ptrie->branch[i],call);
		}
	}

	return;
}

trieStatus trie_destroy(PTrieRoot ptrie_root)
{
	if(!ptrie_root)
		return TRIE_ERROR;

	_trie_rwlock_wrlock(ptrie_root);

	printf("destroy begin\n");
	_trie_destroy(&ptrie_root->proot);
	ptrie_root->proot = NULL;
	printf("destroy end\n");
	_trie_rwlock_unlock(ptrie_root);

	
#if WINDOWS
	CloseHandle(ptrie_root->hMutex);
	ptrie_root->hMutex = 0;
#else

#endif


	return TRIE_SUCCESS;
}

void _trie_destroy(PTrie * pptrie)
{
	int i = 0;

	if(!*pptrie)
		return;

	for(i = 0; i < TRIE_SON_NUM;i++)
	{
		if((*pptrie)->branch[i])
		{
			_trie_destroy(&(*pptrie)->branch[i]);
			trie_free((*pptrie)->branch[i]);
		}
	}
	trie_free(*pptrie);
	*pptrie = NULL;

	return ;
}


  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值