字典树 trie树

本文地址:http://blog.csdn.net/spch2008/article/details/9138557


使用字典树来存储数据,数据是一个键值对,即键值-数值。

字典树允许数据键值共享相同的前缀。本文采用的键值为字符串,数据如下:
amy     56
ann     15
emma    30
rob     27
roger   52
首先存入amy, level 0表示根,不持有数据。其余每个节点持有一个字符;叶子节点持有数据,且持有的字符为'\0'
      .     <- level 0 (root)
      |
      a     <- level 1
      |
      m     <- level 2
      |
      y     <- level 3
      |
    \0 56   <- level 4
添加ann后,后缀树如下,二者共享前缀'a'
         .
         |
         a
       /   \
      m     n
      |     |
      y     n
      |     |
    \0 56 \0 15
下面加入emma,由于emma与之前添加的键值没有相同前缀,所以直接加入根节点下。
              .
          /       \
         a         e
       /   \       |
      m     n      m
      |     |      |
      y     n      m
      |     |      |
    \0 56 \0 15    a
                   |
                 \0 30
将rob与roger加入后,所得字典树如下:
                  .
          /       |      \
         a        e       r
       /   \      |       |
      m     n     m       o
      |     |     |     /   \
      y     n     m    b     g
      |     |     |    |     |
    \0 56 \0 15   a  \0 27   e
                  |          |
                \0 30        r
                             |
                           \0 52

现在有2个问题:
    如果继续添加anne为67,将出现什么状况?
    每个节点有多少个子节点?

解决办法:
    1. 每个节点存放一个数组,可以容纳所有键值中的字符
    2. 采用链表
    3. 左儿子右兄弟表示法

这里我们采用左孩子右兄弟的表示方法。上述数据可以表示为:     
       |
       a --------- e ----- r
       |           |       |
       m --- n     m       o
       |     |     |       |
       y     n     m       b ----- g
       |     |     |       |       |
     \0 56 \0 15   a     \0 27     e
                   |               |
                 \0 30             r
                                   |
                                 \0 52


.h

class TrieTree
{
private:
	struct Node
	{
		char key;
		int  val;
		Node *next, *child;

		Node(char k =' ', int v = 0)
		{
			key = k;
			val = v;
			next = child = NULL;
		}
	};

public:
	TrieTree(void);
	~TrieTree(void);

	bool IsMember(char str[]);
	void Add(char str[], int val);
	void Remove(char str[]);
	int  GetVal(char str[]);
private:
	Node *root;


	Node* _Insert(Node* subtree, char *str, int val);
	Node* _CreateSubTree(char *str, int val);
	Node* _Delete(Node* subtree, char *str);
	Node* _Find(char *str);
	void  _Destroy(Node* subtree);
};

.cpp

TrieTree::TrieTree(void)
{
	root = new Node;
	root->next = root->child = NULL;
}


TrieTree::~TrieTree(void)
{
	_Destroy(root);
}


bool TrieTree::IsMember(char str[])
{
	Node *found = _Find(str);
	
	return found != NULL;
}



void TrieTree::Add(char str[], int val)
{
	root->next = _Insert(root->next, str, val);
}


void TrieTree::Remove(char str[])
{
	root->next = _Delete(root->next, str);
}


int TrieTree::GetVal(char str[])
{
	Node *found = _Find(str);

	if(found == NULL)
		return -1;
	else
		return found->val;
}

TrieTree::Node* TrieTree::_Insert(Node* subtree, char *str, int val)
{
	if(subtree == NULL)
	{
		subtree =  _CreateSubTree(str, val);
	}
	else if(subtree->key != str[0])
	{
		subtree->next =  _Insert(subtree->next, str, val);
	}
	else
	{
		if(str[0] == '\0')     //修改原值
			subtree->val = val;
		else
			subtree->child =  _Insert(subtree->child, &str[1], val);
	}
	return subtree;
}


void TrieTree::_Destroy(Node *subtree)
{
	if(subtree != NULL)
	{
		_Destroy(subtree->child);
		_Destroy(subtree->next);
		delete subtree;
	}
}

TrieTree::Node* TrieTree::_Find(char *str)
{
	int index = 0;
	Node *level = root->next;

	while(true)
	{
		Node *found = NULL;
		//当前层匹配
		for(Node *curr = level; curr != NULL; curr = curr->next)
		{
			if(curr->key == str[index])
			{
				found = curr;
				break;
			}
		}

		if(found == NULL)
			return NULL;

		//不能found->key == str[index]
		//str可以先匹配完成
		if(str[index] == '\0')
			return found;

		//匹配上后,向下在孩子中匹配
		level = found ->child;
		index += 1;
	}

	return NULL;
}


TrieTree::Node* TrieTree::_Delete(Node* subtree, char *str)
{
	if(subtree == NULL)
		return NULL;

	if(subtree->key != str[0])
	{
		subtree->next = _Delete(subtree->next, str);
	}
	else
	{
		if(subtree->key == '\0')
		{
			delete subtree;
			subtree = NULL;
		}
		else
		{
			subtree->child = _Delete(subtree->child, &str[1]);
			if(subtree->next == NULL && subtree->child == NULL)
			{
				delete subtree;
				subtree = NULL;
			}
		}
	}

	return subtree;
}



TrieTree::Node * TrieTree::_CreateSubTree(char *str, int val)
{
	Node *subtree = new Node('\0', val);
	for(int i = strlen(str) - 1; i >= 0; i--)
	{
		Node *node = new Node(str[i]);
		node->child = subtree;
		subtree = node;
	}

	return subtree;	
}


来自:http://www.cs.bu.edu/teaching/c/tree/trie/


1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看REAdMe.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看REAdMe.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看READme.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 、 1资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看READmE.文件(md如有),本项目仅用作交流学习参考,请切勿用于商业用途。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值