IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 双数组trie树详解 -> 正文阅读

[数据结构与算法]双数组trie树详解

双数组trie树的构建

NLP中trie树常用于做快速查询,但普通的trie树由于要保存大量的节点信息,当储存的词量非常大时,不仅所占空间巨大,而且查询的速度也不够快。而双数组trie树就可以比较好的解决这两个问题。

之所以叫双数组trie树,是因为它只用base[]check[]两个数组就将整个trie的信息储存了起来,这两个数组的构建规则是:
b a s e [ i ] + c o d e ( x ) = j c h e c k [ j ] = i \begin{aligned} &base[i] + code(x) = j\\ &check[j] = i \end{aligned} ?base[i]+code(x)=jcheck[j]=i?
其中i,j都是base array的index,base array的长度是trie树中节点的个数,每个节点在base array中都有一个对应的index。

  • base[]数组用于记录跳转结构, base array中index为i的那个节点,如果按照字符x转移,会转移到index为j的节点
  • check[]数组用于 标识出 base array 中每个状态的前一个状态,其主要作用是检验按base做转移的转移正确性
  • code(x)是字符x的编码,现实中为了方便通常直接用char code

构建base array

下面我们看一个例子来学习base array的构建方法:

现在有“清华”、“清华大学”、“清新”、“中华”、“华人”五个词,构成的trie树如下图所示:
在这里插入图片描述
假设例树的字符编码表为:

char
code1234567

初始化root的base index为0,base值记为1。首先看root的所有子节点"清,中,华":

  • base[0] + code(清) = 2,此时位置2空闲,因此“清”放入位置2
  • base[0] + code(中) = 7,此时位置7空闲,因此“中”放入位置7
  • base[0] + code(华) = 3,此时位置3空闲,因此“中”放入位置3

目前base array的情况如下:

position012345678910
charroot
base1
  • 每次遍历完一个节点的所有子节点,只可以确认当前节点的base值,以及它的子节点的index位置
  • 子节点的base值此时会默认继承当前节点的base值,但在遍历子节点的子节点时,一旦有冲突,子节点的base值就会做相应修改

接下来遍历第二层的节点"华,新,华,人":

  • base[2] + code(华) = 3,冲突!因此 base[2] 修改为2;base[2] + code(华) = 4,可用,因此 “清华” 放入位置4
  • base[2] + code(新) = 7,冲突!因此 base[2] 修改为3;base[2] + code(新) = 8,可用,因此 “清新” 放入位置8
  • 因为base[2] 再次北被修改,所以“清华”的位置要重新计算:base[2] + code(华) = 5,可用,因此 “清华” 放入位置5
  • base[7] + code(华) = 3,冲突!因此 base[7] 修改为2;base[7] + code(华) = 4,可用,因此 “中华” 放入位置4
  • base[3] + code(人) = 8,冲突!因此 base[3] 修改为2;base[3] + code(人) = 9,可用,因此 “华人” 放入位置9

目前base array的情况如下:

position012345678910
charroot中华清华清新华人
base1322

接下来遍历第三层的节点"大":

  • base[5] + code(大) = 6,可用;因此 “清华大” 放入位置6

目前base array的情况如下:

position012345678910
charroot中华清华清华大清新华人
base13223

接下来遍历第四层的节点"学":

  • base[6] + code(学) = 7,冲突!base[6] 修改为4;base[6] + code(学) = 8,还是冲突!base[6] 修改为5;base[6] + code(学) = 9,还是冲突!base[6] 修改为6;base[6] + code(学) = 10,可用,因此 “清华大学” 放入位置10

目前base array的情况如下:

position012345678910
charroot中华清华清华大清新华人清华大学
base132623

此时节点已经遍历完,剩余base值未确定的都是尾节点了,因为它们都没用子节点了,所以不存在位置冲突,因此可以直接继承父节点的base值

position012345678910
charroot中华清华清华大清新华人清华大学
base1322362326

构建check array

check array的构建比较简单,只需要将子节点index的check值设为父节点的base值即可,所以有:

position012345678910
charroot中华清华清华大清新华人清华大学
base1322362326
check-2007250236

双数组trie树的查询

此时如果有一个词“清中”,我们要查询它是否在双数组trie里面,那么首先从root出发,由于“清”的code是1,因此会走到 base[0]+code(清) = 2,这里要用check数组检查位置3上的节点其父节点是否是位置0上的节点:check[2] = 0,等式成立!

然后继续看“中”:base[2]+code(中) = 9,再检查位置9上的节点的父节点是否是位置2上的节点:check[9] = 3 !=2 ,检查发现不满足,因此"清中"不在该trie里面。


Reference:
小白详解 Trie 树
double-array-trie双数组trie树原理解析和数据构建过程

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2021-12-06 15:30:50  更:2021-12-06 15:32:50 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 14:39:51-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码