字典树(trie树)

45 篇文章 0 订阅
43 篇文章 0 订阅

Trie树又称字典树、单词查找树,是一种树形结构,用于保存大量的字符串。

优点:利用字符串的公共前缀来节约存储空间。

缺点:如果Trie树中存在大量字符串,并且这些字符串基本上没有公共前缀,那么相应的Trie树将非常消耗内存空间,Trie的缺点是空指针耗费内存空间。

基本性质

(1)根节点不包含字符,除根节点外的每个节点只包含一个字符。

(2)从根节点到某一个节点,路径上经过的字符连接起来,为该节点对应的字符串。

(3)每个节点的所有子节点包含的字符串不相同。

基本操作有:查找、插入和删除

假设,我们要构建一个26个字母的Trie树,那么每一个指针对应着字母表里的一个字母。从根节点开始,我们只要依次找到目标单词里下一个字母对应的指针,就可以一步步查找目标了。

如图所示,该trie树存有abc、d、da、dda四个字符串,如果是字符串会在节点的尾部进行标记。没有后续字符的分支指向NULL。

Trie时间复杂度分析:

          对于insert, 如果被插入的String长度是 k, 每对一个字符进行查询,我们最多在child linkedlist里面查询26次(最多26个字母),所以,复杂度为O(26*k) = O(k).

          对于 search, 复杂度是一样的。


Trie空间复杂度分析:

          空间复杂度是26的n次方,非常庞大(可采用双数组实现改善)


Tire树的应用:

          1  字符串检索

          2  字符串最大公共前缀

          3  排序(Trie树是一颗多叉树,只要前序遍历整棵树,输出相应的字符串便是按字典排序的结果)

          4  其它数据结构的辅助结构(后缀树、AC自动机)

#include <iostream>
using namespace std;

const int MAX_NUM = 26;
//Trie 树的结点类型
struct Node
{
      bool COMPLETED;		//COMPLETED为true时表示目前产生一个字符串
      char ch;
      struct Node *child[MAX_NUM]; //26-tree->a, b ,c, .....z
};

//Trie树类
class Trie
{
public:
	Trie();
	~Trie();
	Node* CreateNewNode(char ch);//创建一个新结点
	void InitTrie();//初始化Trie树
	int CharToindex(char ch);//找到字母对应的数组下标
	int Find(const char chars[], int len);//找到长度为len的字符串
	void Insert(const char chars[], int len);//插入长度为len的字符串
	void Delete();//删除整棵树

private:
	void DeleteTree (Node *& root);
	Node* root; //根结点
};

Trie::Trie()
{
	root = NULL;
}

Trie::~Trie()
{

}

Node* Trie::CreateNewNode(char ch)//创建一个新的结点
{
	Node *new_node = new Node;
	new_node->ch = ch;
	new_node->COMPLETED = false;
	
	for(int i=0; i<MAX_NUM ; i++)
	{
		new_node->child [i] = NULL;
	}
	return new_node ;
}

void Trie::InitTrie()//构建一棵空树
{
	root = CreateNewNode(' ');
}

int Trie::CharToindex(char ch)
{
	return ch - 'a';
}

int Trie::Find(const char chars[], int len)
{
	if (root == NULL)
	{
		cout << "树为空!" << endl;
		return 0;
	}
	
	Node* ptr = root;
	int i = 0;
	while(i < len)
	{
		if(ptr ->child[ CharToindex(chars [i])] == NULL)
		{
			break;
		}
		ptr = ptr ->child[ CharToindex(chars [i])];
		i++;
	}
	return (i == len) && ( ptr->COMPLETED == true);
}

void Trie::Insert(const char chars[], int len)//向 Trie树中插入长度为len的字符串
{
	Node* ptr = root;
	
	for(int i = 0; i < len ; i++)
	{
		if(ptr->child[CharToindex(chars[i])] == NULL)
		{
			ptr->child[CharToindex(chars[i])] = CreateNewNode(chars[i]);
		}
		ptr = ptr->child[CharToindex(chars[i])];
	}
	ptr->COMPLETED = true;
}

void Trie::Delete()//利用递归删除整棵树
{
	DeleteTree(root);
}

void Trie::DeleteTree(Node *&Root)//利用递归删除整棵树 注意此处应该加上应用
{
	if (Root == NULL)//递归出口
	{
		return;
	}
	
	for (int i=0; i<MAX_NUM ; i++)
	{
		if (Root ->child[ i] != NULL )
		{
			DeleteTree(Root ->child[ i]);
		}
	}
	
	delete Root;
	Root = NULL;       
}

int main(int argc, char *argv[])
{
	char *a = "ten";
	char *b = "tea";
	Trie trie;
	trie.InitTrie ();
	trie.Insert (a, 3);
	trie.Insert (b, 3);
	//trie.Insert (a, 3);
	cout<<trie.Find(a, 3)<<endl;
	trie.Delete ();
	cout<<trie.Find(b, 3)<<endl ;
	
	return 0;
}

Reference:

http://blog.csdn.net/htyurencaotang/article/details/7844360


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值