赞
踩
又称为字典树、单词查找树。是一种树形结构,哈希树的变种。典型应用是用于统计、排序和保存大量的字符串(不仅仅限于字符串),经常被搜索引擎系统用于文本词频统计。trie树是用空间换取时间的典型数据结构。
根节点不包含字符,除了根节点外,每个节点都只包含一个字符;
从根节点到某一节点,路径上经过的字符连接起来,为该节点对应的字符串;
每个节点的所有子节点包含的字符都不相同。
基本操作有:树的创建、删除;节点的插入、查找、删除(好像这种操作比较少见)。
利用字符串的公共前缀来减少查询时间,最大限度地减少无谓的字符串比较,查询效率比哈希表高
每个节点需要包含一些额外的字段来保存节点信息,浪费空间。
串的快速检索、“串”排序、最长公共前缀
本文实现了trie树的创建、删除;字符串的插入、查找、删除。另外,本文限定单词仅仅由26个小写字母组成。具体实现将在本文最后给出完整代码。
- typedef struct TrieNode
- {
- int isStr; /*word flag*/
- int elemcount; /*word number*/
- int passcount; /*pass by number*/
- struct TrieNode *next[MAX];
- }Trie;
其中,isStr 单词结束标记;elemcount是单词被插入的次数;passcount是所有单词经过该节点的次数;next是该节点的孩子节点。
创建trie树与trie树初始化,分开实现。
- Trie * trie_malloc();
- void trie_init(Trie *p);
删除整棵树,释放其拥有的所有资源
void trie_del(Trie *root);
将字符串s插入trie树root
void trie_insert(Trie *root,const char *s);
从trie树中查找字符串s,如果能找到则返回s在trie中出现的次数(即被插入的次数),否则返回0
int trie_search(Trie *root,const char *s);
trie树中删除字符串s(s是整个单词,并不会删除一个完整单词的一部分)
void trie_node_del(Trie *root, const char *s);
这些辅助函数相当于C++的private成员,仅仅用来辅助实现基本的用户功能。分别为:验证字符串的合法性、根据字符获取在孩子节点中的索引、递归删除trie树、递归删除字符串对应的节点
- static int verify_str(const char *s);
- static int get_index(char ch);
- static void delete_subtrie(Trie **root);
- static void delete_node(Trie **node, const char *chr);
具体的代码实现trie.h如下:
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
-
- #define MAX 26
- #define IDXERR -1
- #define INVALID 0
- #define VALID 1
-
- #define true 1
- #define false 0
-
- typedef struct TrieNode
- {
- int isStr; /*word flag*/
- int elemcount; /*word number*/
- int passcount; /*pass by number*/
- struct TrieNode *next[MAX];
- }Trie;
-
- Trie * trie_malloc();
- void trie_init(Trie *p);
-
- void trie_insert(Trie *root,const char *s);
- int trie_search(Trie *root,const char *s);
- void trie_del(Trie *root);
- void trie_node_del(Trie *root, const char *s);
-
- static int verify_str(const char *s);
- static int get_index(char ch);
- static void delete_subtrie(Trie **root);
- static void delete_node(Trie **node, const char *chr);
-
- void trie_init(Trie *p)
- {
- int i=0;
- if(NULL == p)
- return;
- memset(p,0x0,sizeof(Trie));
- for(i=0;i<MAX;i++)
- {
- p->next[i] = NULL;
- }
- p->isStr = false;
- p->elemcount = 0;
- p->passcount = 0;
- }
-
- Trie * trie_malloc()
- {
- Trie *temp=(Trie *)malloc(sizeof(Trie));
- return temp;
- }
-
- void trie_insert(Trie *root,const char *s)
- {
- if(NULL == root || NULL == s || *s == '\0')
- return;
- if(INVALID == verify_str(s))
- return;
- Trie *p = root;
- int idx = 0;
- while(*s!='\0')
- {
- idx = get_index(*s);
- if(NULL == p->next[idx])
- {
- Trie *temp = trie_malloc();
- trie_init(temp);
- p->next[idx]=temp;
- p=p->next[idx];
- }
- else
- {
- p=p->next[idx];
- }
- s++;
- p->passcount++;
- }
- p->isStr=true;
- p->elemcount++;
- }
-
- int trie_search(Trie *root,const char *s)
- {
- Trie *p=root;
- int idx = 0;
- if(NULL == root || NULL == s)
- return 0;
- while(p != NULL && *s != '\0')
- {
- idx = get_index(*s);
- if(IDXERR == idx)
- return 0;
- p=p->next[idx];
- s++;
- }
- if(p != NULL && true == p->isStr)
- return p->elemcount;
- else
- return 0;
- }
-
- void trie_del(Trie *root)
- {
- if(NULL == root)
- return;
- delete_subtrie(&root);
- }
-
- static int verify_str(const char *s)
- {
- if(NULL == s)
- return INVALID;
- while(*s!='\0')
- {
- if(IDXERR == get_index(*s))
- return INVALID;
- s++;
- }
- return VALID;
- }
-
- static int get_index(char ch)
- {
- int idx = ch-'a';
- if(idx < 0 || idx >= MAX)
- {
- idx = IDXERR;
- }
- return idx;
- }
-
- static void delete_subtrie(Trie **root)
- {
- int i = 0;
- if(root != NULL && *root != NULL)
- {
- for(i = 0; i < MAX; i++)
- {
- if((*root)->next[i]!=NULL)
- {
- delete_subtrie(&((*root)->next[i]));
- }
- }
- }
- if(NULL != root)
- {
- free(*root);
- *root = NULL;
- }
- }
-
-
- static void delete_node(Trie **node, const char *chr)
- {
- int idx = 0;
- if(NULL == node || NULL == *node || NULL == chr)
- return;
- if(*chr != '\0'&& *(chr+1) != '\0' && *node != NULL)
- {
- chr++;
- idx = get_index(*chr);
- delete_node(&((*node)->next[idx]), chr);
- }
- if(*node != NULL)
- {
- free(*node);
- *node = NULL;
- }
- return;
- }
-
- void trie_node_del(Trie *root, const char *s)
- {
- if(NULL == root || NULL == s || *s == '\0')
- return;
- int elemcount=0;
- Trie *p = root;
- Trie *q = p;
- int remain=0;
- int idx = 0;
- if((elemcount=trie_search(root,s))<= 0)
- return;
- while(*s != '\0' && p != NULL)
- {
- idx = get_index(*s);
- q = p;
- p = p->next[idx];
- remain = p->passcount - elemcount;
- if(remain <= 0)
- {
- delete_node(&p, s);
- q->next[idx] = p; // important
- p = NULL;// can delete "p = NULL"
- break;
- }
- else
- {
- p->passcount = remain;
- }
- s++;
- }
- /*clear word flag*/
- if(p != NULL)
- {
- p->isStr = false;
- }
- }
测试代码main.c
- #include "trie.h"
-
- #define STR1 "hello"
- #define STR2 "hell"
- #define STR3 "helloworld"
- #define STR4 "world"
- #define STARLINE "****"
-
- int main(int argc, char *argv[])
- {
- Trie *root= trie_malloc();
- if(NULL == root)
- {
- printf("malloc trie failed\n");
- exit(0);
- }
- trie_init(root);
-
- /*insert*/
- printf("\n %sinsert string%s\n",STARLINE,STARLINE);
- trie_insert(root,STR1);
- printf("%s\n",STR1);
- trie_insert(root,STR2);
- printf("%s\n",STR2);
- trie_insert(root,STR3);
- printf("%s\n",STR3);
- trie_insert(root,STR4);
- printf("%s\n",STR4);
- trie_insert(root,STR2);
- printf("%s\n",STR2);
- /*search*/
- printf("\n %ssearch string%s\n",STARLINE,STARLINE);
- printf("%s, %d times\n",STR1, trie_search(root,STR1));
- printf("%s, %d times\n",STR2, trie_search(root,STR2));
- printf("%s, %d times\n",STR3, trie_search(root,STR3));
- printf("%s, %d times\n",STR4, trie_search(root,STR4));
- /*delete*/
- printf("\n %sdelete string%s\n",STARLINE,STARLINE);
- trie_node_del(root, STR1);
- printf("%s\n", STR1);
- printf("search %s, %d times\n",STR1, trie_search(root,STR1));
-
- trie_node_del(root, STR2);
- printf("%s\n", STR2);
- printf("search %s, %d times\n",STR2, trie_search(root,STR2));
-
- trie_node_del(root, STR3);
- printf("%s\n", STR3);
- printf("search %s, %d times\n",STR3, trie_search(root,STR3));
-
- trie_node_del(root, STR4);
- printf("%s\n", STR4);
- printf("search %s, %d times\n",STR4, trie_search(root,STR4));
-
- /*free trie*/
- printf("\n %sfree trie%s\n",STARLINE,STARLINE);
- trie_del(root);
- root = NULL;
-
- return 0;
- }
gcc -g -o test main,c
执行结果如下图:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。