C语言实现Trie树(字典树)的插入查找删除与遍历操作

原创 2018年04月15日 15:07:42

Trie树,也称作是字典树,是一种哈希树的变种,查询效率较高。Trie树可以用于统计或者排序大量的字符串,比如对一系列字符串按照字典序排序。

字典树是一个多叉树,每一个节点上存储的不是一个字符串,而是一个字符,从根节点到某个节点的路径上的所有字符串联起来就构成了一个字符串。

对于N个字符串,如果其平均长度为M,则建立字典树的算法复杂度为O(M*N),在字典树上查找某个长度为M的字符串的算法复杂度O(M),字典树可以边搜索边建立,因此总的查找算法复杂度为O(M*N)。

C语言实现Trie树(字典树)的插入查找删除与遍历操作如下:

/*
 * Trie tree algorithm dmo
 */
 
# include <stdio.h>
# include <stdlib.h>
# include <string.h>

#define MAXSTRLEN 1024

typedef struct TRIETREENODE
{
	int cnt;                       /*统计各个单词出现的次数 初始化为0*/
	struct TRIETREENODE *next[26]; /*假设单词只有字母*/
}TrieTreeNode;

TrieTreeNode *createTrieTreeNode();                        /*新建并初始化一个节点*/
int InsertTrieTreeNode(TrieTreeNode *ptrRoot, char *str);  /*插入一个单词*/
int DeleteTrieTreeNode(TrieTreeNode *ptrRoot, char *str);  /*删除一个单词*/
int SearchTrieTree(TrieTreeNode *ptrRoot, char *str);      /*搜索Trie树*/
void TraverseTrieTree(TrieTreeNode *ptrRoot);              /*遍历Trie树*/
void DestroyTrieTree(TrieTreeNode *ptrRoot);               /*销毁Trie树*/

/*新建并初始化一个节点*/
TrieTreeNode *createTrieTreeNode()
{
	TrieTreeNode *treeNode = NULL;

	/*申请内存*/
    treeNode = (TrieTreeNode*)malloc(sizeof(TrieTreeNode));
	if(treeNode == NULL)
	{
		printf("Error! malloc error.\n");
		return NULL;
	}
	
	/*初始化*/
	memset(treeNode->next, 0x00, sizeof(treeNode->next));
	treeNode->cnt = 0;

	return treeNode;
}

/*插入一个单词*/
int InsertTrieTreeNode(TrieTreeNode *ptrRoot, char *str)
{
	int i, index;
	TrieTreeNode *tempNode = ptrRoot;
	
	if(ptrRoot==NULL || str == NULL || str[0]=='\0') /*Trie树带有一头结点*/
		return 0;
	
	for(i=0;i<strlen(str) ;i++)
	{
		if(str[i]<'a' && str[i]>'z')  /*只能含有a-z之间的字母*/
		{
			printf("Invalid lettre[%c]\n", str[i]);
			return -1;
		}

		index = str[i]-'a';
        if(tempNode->next[index] != NULL)
		{
			tempNode  = tempNode->next[index];
			continue;
		}

        tempNode->next[index] = createTrieTreeNode();
        if(tempNode->next[index] == NULL)
	    {
	    	printf("createTrieTreeNode error.\n");
	    	return -1;
	    }
        tempNode  = tempNode->next[index];		
	}
	
	tempNode->cnt = tempNode->cnt + 1;
	return 0;
	
}


/*
 * 搜索Trie树
 * exist return count of target
 * not exist return 0
 */
int SearchTrieTree(TrieTreeNode *ptrRoot, char *str)
{
	 int i, index; 
	 TrieTreeNode *tempNode = ptrRoot;
	 
	 if(ptrRoot==NULL || str == NULL) 
		return 0;
	
	for(i=0;i<strlen(str) ;i++)
	{
		index = str[i]-'a';
        if(tempNode->next[index] == NULL)
		{
			return 0;
		}
		tempNode  = tempNode->next[index];
	}
	
	return tempNode->cnt;
}  

/*
 * not exist return 0
 * exist return (node->cnt - 1)
 */
int DeleteTrieTreeNode(TrieTreeNode *ptrRoot, char *str)
{
	int i, index; 
	TrieTreeNode *tempNode = ptrRoot;
	 
	if(ptrRoot==NULL || str == NULL) 
		return 0;
	
	for(i=0;i<strlen(str) ;i++)
	{
		index = str[i]-'a';
        if(tempNode->next[index] == NULL)
		{
			return 0;
		}
		tempNode  = tempNode->next[index];
	}
	tempNode->cnt = tempNode->cnt-1;
	return tempNode->cnt;
}

/*遍历Trie树,使用静态变量,递归时可以记录之前一层上的字符*/
void TraverseTrieTree(TrieTreeNode *ptrRoot)
{
	int i;
	static char word[MAXSTRLEN + 1] ={0};
	static int j=0;
	
	if(ptrRoot==NULL) 
		return;

	for(i=0; i<26; i++)
	{
		if(ptrRoot->next[i] == NULL)
		{
			continue;
		}

		word[j++] = i + 'a';
		if(ptrRoot->next[i]->cnt > 0)
		{
			word[j+1] = '\0';
			printf("%-20s %-8d\n",word, ptrRoot->next[i]->cnt);
		}
		TraverseTrieTree(ptrRoot->next[i]);
	    j--;
			
	}
	
	return;
}

/*销毁Trie树*/
void DestroyTrieTree(TrieTreeNode *ptrRoot)
{
	int i;
	
	if(ptrRoot==NULL) 
		return;
	
	for(i=0; i<26; i++)
	{
		if(ptrRoot->next[i] != NULL)
		{
			DestroyTrieTree(ptrRoot->next[i]);
		}
	}
	
	free(ptrRoot); /*子节点全部删除后就才可以释放根节点*/
	ptrRoot = NULL;
	
	return ;
}            

int main()
{
	int N;
	int i;
	int ret;
	char str[100][1024+1] = {0};
	char word[1024+1] = {0};
	TrieTreeNode *ptrRoot = NULL;
	
	/*input*/
	printf("Please input an positive integer N which is between 1 and 100.\n");
	scanf("%d", &N);
	if(N <= 0 || N >100)
	{
		printf("Invalid input N[%d]\n", N);
		return -1;
	}
	
	printf("Please input %d words whic contain only letters.\n", N);
	for(i=0; i<N; i++)
	{
		scanf("%s", *(str+i));
	}
	
	/*create  head code*/
	ptrRoot =  createTrieTreeNode();
	if(ptrRoot == NULL)
	{
		printf("createTrieTreeNode error.\n");
		return -1;
	}
	
	/*build tree */
	for(i=0; i<N; i++)
	{
		printf("%s ", *(str+i));
		ret = InsertTrieTreeNode(ptrRoot,*(str+i));
		if(ret != 0)
		{
			printf("InsertTrieTreeNode error.\n");
		    return -1;
		}
	}
	printf("\n");
	
	printf("TraverseTrieTree:\n");
	TraverseTrieTree(ptrRoot);
	
	printf("Please input an word.\n", word);
	scanf("%s", word);
	
	printf("Search %s in the tree. cnt=[%d]\n", word,SearchTrieTree(ptrRoot,word));
	
	printf("Delete %s in the tree. cnt=[%d]\n", word,DeleteTrieTreeNode(ptrRoot,word));
	
	printf("TraverseTrieTree:\n");
	TraverseTrieTree(ptrRoot);
	
	printf("DestroyTrieTree\n");
	DestroyTrieTree(ptrRoot);
	ptrRoot = NULL;
	
	printf("TraverseTrieTree:\n");
	TraverseTrieTree(ptrRoot); 
	
	return 0;
}  

测试结果如下:


Trie树:应用于统计和排序 && 倒排索引

1. 什么是trie树   1.Trie树 (特例结构树)         Trie树,又称单词查找树、字典树,是一种树形结构,是一种哈希树的变种,是一种用于快速检索的多叉树结构。典型应用是用...
  • yangxuefeng09
  • yangxuefeng09
  • 2015-08-16 09:01:35
  • 1382

Trie树详解及其应用

一、知识简介         最近在看字符串算法了,其中字典树、AC自动机和后缀树的应用是最广泛的了,下面将会重点介绍下这几个算法的应用。       字典树(Trie)可以保存一些字符串->值的对应...
  • Hackbuteer1
  • Hackbuteer1
  • 2012-09-10 16:49:32
  • 57672

遍历-字典里面取键

输入字符串——–输出为 字典 输入字符串 并统计字符串重叠单个次数 a = '小明456fgdddhhh55adbyjjjjj' m ={} for ch in a : # 从a字符串...
  • weixin_41782332
  • weixin_41782332
  • 2018-03-24 11:44:49
  • 83

字典树(Trie树)的C程序实现代码

#include #include #include #define MAX 256//ascii码有256个字符,故每棵树的子节点最多有256个 #define MAXLEN 25...
  • sjjbupt
  • sjjbupt
  • 2011-09-07 22:20:43
  • 5186

字典树Trie 之 基础模板(插入,查找,删除)

/* #include using namespace std; const int maxn = 26;//26个小写字母或者大写字母,再加上0~9就是72 //定义字典树结构体 ...
  • u010700335
  • u010700335
  • 2014-08-29 20:44:14
  • 1699

ios之遍历字典

1、使用for-each循环遍历字典中的对象,可以通过如下代码实现: for (NSString *s in [dictionary allValues]) {     NSLog(@"value...
  • LVXIANGAN
  • LVXIANGAN
  • 2015-08-28 11:13:29
  • 24944

简单介绍一下字典的遍历

大家可能都知道字典这种数据结构吧!但是对于字典的遍历都清楚吗? 下面就提供几种方法吧!不说多了,直接来代码吧!using System.Collections; using System.Colle...
  • qq_37601496
  • qq_37601496
  • 2017-11-20 11:57:47
  • 168

高级数据结构的学习与实现之 Trie树,字典树

第一次自学一种新的数据结构,感觉学会利用资源很重要,参考别人写的博客,谷歌搜索一下关于这中数据结构的一些问题,解决等,学会搜索资料,学习并掌握一门数据结构并不是很难。 要知道相关的基本知识,主要应用与...
  • guin_guo
  • guin_guo
  • 2015-10-02 09:43:15
  • 1728

Trie 字典树 删除操作

字典树的删除操作: 1 没找到直接返回 2 找到叶子节点的时候,叶子节点的count标志清零,代表不是叶子节点了 3 如果当前节点没有其他孩子节点的时候,可以删除这个节点 判断是否需是叶子节点...
  • kenden23
  • kenden23
  • 2014-05-30 20:48:18
  • 2276

Trie原理以及应用于搜索提示

Trie又称前缀树或字典树,是一种有序树,用于保存关联数组,其中的键通常是字符串。与二叉查找树不同,键不是直接保存在节点中,而是由节点在树中的位置决定。...
  • WSYW126
  • WSYW126
  • 2017-03-11 13:52:30
  • 1936
收藏助手
不良信息举报
您举报文章:C语言实现Trie树(字典树)的插入查找删除与遍历操作
举报原因:
原因补充:

(最多只允许输入30个字)