字典树(T树)

目录

什么是T树(字典树)

T树的定义

构建一个T树

构建树的节点

(1)分支表示

(2)元素表示

(3)T树节点的表示:

总体关系设计

T树的查找

​编辑

代码

T树的插入

 代码

T树删除


什么是T树(字典树)

        字典树又称单词查找树,Trie树,是一种树形结构,是一种哈希树的变种。典型应用是用于统 计,排序和保存大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计。它的优点是:利用字符串的公共前缀来减少查询时间,最大限度地减少无谓的字符串比较,查询效率比哈希树高。

T树的定义

Trie树是一颗度m>=2的树,它的每一层分支不是靠整个关键码的值来确定,而是由关键码的一个分量来确定。

如图所示键树中,从结点Z到结点$为单支树,则在图相应的Trie树中只有一个含有关键字ZHAO及相关信息的叶子结点。由此,在Trie树中有两种结点:分支结点(含有d个指针域和一个指示该结点中非空指针域的个数的整数域)和叶子结点(含有关键字域和指向记录的指针域)。在分支结点中不设数据域,每个分支结点所表示的字符均由其双亲结点中(指向该结点)的指针所在位置决定。

构建一个T树

构建树的节点

由上图可以看出一颗T树由两大部分组成,即分支和元素(存取的值);

(1)分支表示

分支(Brch)是由一个数组组成,数组的每一个位存放的是树的指针,第一位位空(存放是该分支的共同元素);设计分支如下:

typedef struct 
{
   TrieNode* link[LETLEN];
}BrchType;

(2)元素表示

从图中可以看出,我们存放的每一个元素都有自己的大小和值组成;所以设计元素如下:

typedef struct
{
	char ch[MaxKeySize];
	int curentSize;
}KeyType;

typedef struct
{
	KeyType key;
	Record * recptr;
}ElemType;

(3)T树节点的表示:

因为图中可以看出每次层要么是分支要么是元素;为了节省空间可以设计为联合体;

struct TrieNode
{
	NodeType utype; // ELEM , BRCH
	union
	{
		ElemType item;
		BrchType brch;
	};
};

总体关系设计

const int MaxKeySize = 25;
const int LETLEN = 27;
typedef enum { BRCH = 0, ELEM = 1 } NodeType;

typedef struct
{
	char ch[MaxKeySize];//分支,大小26个字母,0位置有其他含义
	int curentSize;//单词的长度
}KeyType;
typedef struct{ }Record;//记录集
typedef struct
{
	TrieNode* link[LETLEN];
}BrchType;
typedef struct
{
	KeyType key;//关键码
	Record* recptr;//记录集指针
}ElemType;
struct TrieNode
{
	NodeType utype;
	union
	{
		ElemType item;
		BrchType brch;
	};
};

T树的查找

在T树上进行查找的过程为:从根结点出发,沿和给定值相应的指针逐层向下,直至叶子结点,若叶子结点中的关键字和给定值相等,则查找成功,若分支结点中和给定值相应的指针为空,或叶结点中的关键字和给定值不相等,则查找不成功。
 

代码

	TrieNode* root;
	static int Index(const KeyType& kx, int k)
	{
		int index = 0;
		if (k < kx.curentSize)
		{
			index = kx.ch[k] - 'a' + 1;
		}
		return index;
	}
TrieNode* Find(const KeyType& kx)
	{
		TrieNode* p = root;
		int k=0;
		while (p != nullptr && p->utype == BRCH)
		{
			int index = Index(kx, k);
			k += 1;
			p = p->brch.link[index];
		}
		if (p != nullptr && strcmp(kx.ch, p->item.key.ch) != 0)
		{
			p = nullptr;
		}
		return p;
	}

T树的插入

T树的插入也是非常容易理解,大致分为这几个步骤,以插入这几个单词为例{“cha”,"baby","chain","long"};

(1)先对传入的根节点判断是否为空,如果为空则建立根元素节点,直接连接根节点,也就是插入第一个单词“cha”

 (2)如果根节点不为空,开始查询对应位置,如果是元素则改为分支,再连接;

(3) 如果根节点不为空,开始查询对应位置,如果是分支则连接;

 代码

static TrieNode* Buynode()
	{
		TrieNode* s = (TrieNode*)malloc(sizeof(TrieNode));
		if (nullptr == s)exit(1);
		memset(s, 0, sizeof(TrieNode));
		return s;
	}
	static TrieNode* MakeElem(const ElemType& item)
	{
		TrieNode* s = Buynode();
		s->utype = ELEM;
		s->item = item;
		return s;
	}
	static TrieNode* MakeBrch(TrieNode* ptr, int k)
	{
		TrieNode* s = Buynode();
		s->utype = BRCH;
		int index = Index(ptr->item.key, k);
		s->brch.link[index] = ptr;
		return s;
	}
void Insert_Item(TrieNode*& ptr, const ElemType& item, int k)
	{
		if (ptr == nullptr)
		{
			ptr = MakeElem(item);
		}
		else if (ptr->utype == BRCH)
		{
			int index = Index(item.key, k);
			Insert_Item(ptr->brch.link[index], item, k + 1);
		}
		else if (ptr->utype == ELEM)
		{
			ptr = MakeBrch(ptr, k);
			int index = Index(item.key, k);
			Insert_Item(ptr->brch.link[index], item, k + 1);
		}
	}

T树删除

可以给分支域中加一个计数值,当插入新元素时就使其加1,反之等于0时将其分支删除,但是没多大意义;

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值