PHP数据结构(十四) ——键树(双链树)
时间:2022-05-03
本文章向大家介绍PHP数据结构(十四) ——键树(双链树),主要内容包括相关阅读:、PHP数据结构(十二) ——静态查找表、PHP数据结构(十一) ——图的连通性问题与最小生成树算法(2)、PHP数据结构(十一) ——图的连通性问题与最小生成树算法(1)、PHP数据结构(十) ——有向无环图与拓扑算法、PHP数据结构(九) ——图的定义、存储与两种方式遍历、PHP数据结构(八) ——赫夫曼树实现字符串编解码(实践2)、PHP数据结构(八) ——赫夫曼树实现字符串编解码(实践1)、PHP数据结构(八) ——赫夫曼树实现字符串编解码(理论)、PHP数据结构(七) ——串与实现KMP算法、PHP数据结构(六) ——树与二叉树之概念及存储结构、PHP数据结构(六) ——数组的相乘、广义表、PHP数据结构(五) ——数组的压缩与转置、PHP数据结构(四) ——队列、PHP数据结构(三)——运用栈实现括号匹配、PHP数据结构(二)——链式结构线性表、PHP数据结构(一)——顺序结构线性表、基本概念、基础应用、原理机制和需要注意的事项等,并结合实例形式分析了其使用技巧,希望通过本文能帮助到大家理解应用这部分内容。
PHP数据结构(十四)
——键树(双链树)
(原创内容,转载请注明来源,谢谢)
一、概念
键树又称为数字查找树,该树的度>=2,每个节点不是存储关键字,而是存储组成关键字的一个字符或数值的一个数字。例如现有下列字符串:lin、li、linhxx、php、pdo、phper,使用键树存储的结果如下图:
从上图可以看出,键树由一个不代表任何内容的根节点、若干字符节点和一个结束节点组成,结束节点统一用$表示。
二、存储
键树有两种存储方式,一种称为双链树存储,另一种称为多重链表存储(又称Trie树)。
1、双链树存储
以树的孩子兄弟表示键树,每个节点包括三个域:symbol域,存储关键字的字符;first域,存储第一棵子树的节点;next域,存储下一个兄弟指针。
双链树对于查找而言非常便利,而对于增加、删除节点较为复杂。双链树存储如下图所示。
从双链树进行查找和插入的方法,即字符串逐个比较的方法,用第一个字符和根节点下面的所有第一级子节点进行比较,如果存在则进入该子树,再用第二个字符和子树的第一级子节点进行比较;如果比较失败,则插入一个子树。
编程思想:
1)把字符串逐个进行遍历,遍历第一个字符串的时候在双链树的第一行,第二个进入第二行;
2)先横向遍历,如果没有找到节点,则生成一个节点,并让上一个兄弟节点指向该节点,再进入其子节点进行循环。如果找到节点,则直接进入其子节点。
3)子节点生成后,需要将其父节点指向该子节点。
4)代码的关键在于用两个临时栈,一个是兄弟节点栈,在横向遍历的时候暂存;一个是双亲节点栈,用于在纵向遍历的时候暂存。
代码执行结果如下:
源码如下:
<?php
//键树-双链树结构-节点
class Node{
public $symbol;//标记字符
public $last;//标记第一个兄弟节点
public $first;//标记第一个子节点
public function __construct($symbol =null, $first = null, $last = null){
$this->symbol = $symbol;
$this->first = $first;
$this->last = $last;
}
}
classDoubleLinkKeyTree{
private $tree;
public function __construct(){
$this->tree = newNode();//根节点
$this->tree->first =new Node();
}
//构造双链树
//格式:array($str1,$str2, $str3)
public function generate(array$arrStr){
//初始情况:把最后一个字符串直接生成到树
$strLast =array_pop($arrStr);//剔除最后一个字符串,采用最后一个不采用第一个是因为array_pop速度比array_shift快
$strLast .= '$';//加上结束符
$curNode = $this->tree;
for($i=0;$i<strlen($strLast);$i++){
$curNode->first =new Node($strLast[$i]);
$curNode =$curNode->first;
}
$curNode =$this->tree->first;//当前节点回到根节点的第一个子树
$broStack = array();//兄弟节点栈
$parStack = array();//双亲节点栈
//逐个字符串生成双链树的节点
foreach($arrStr as $str){
$str .= '$';//加上结束符
//遍历字符串str的每一个字符
for($i=0;$i<strlen($str);$i++){
//如果节点是空,则
if(null ==$curNode){
//获取双亲节点
$parNode= array_pop($parStack);
//构造子节点并入栈
$curNode= new Node($str[$i]);
array_push($parStack,$curNode);
//修改双亲阶段指向
$parNode->first= $curNode;
//修改子节点指向
$curNode= $curNode->first;
continue;
}
//遍历兄弟节点
while(null!= $curNode && $curNode->symbol != $str[$i]){
array_push($broStack,$curNode);
$curNode= $curNode->last;
}
if(null ==$curNode){
//回溯上一个兄弟节点
$lastNode= array_pop($broStack);
//建立节点并入栈
$curNode= new Node($str[$i]);
array_push($parStack,$curNode);
//将上一个节点指向该节点
$lastNode->last= $curNode;
//开始遍历该节点的子节点
$curNode= $curNode->first;
continue;
}
//如果兄弟节点找到相同的节点,则遍历子节点
if($curNode->symbol== $str[$i]){
array_push($parStack,$curNode);
$curNode= $curNode->first;
continue;
}
$broStack =array();//释放兄弟节点栈(因为每一个字符结束要去下一行搜索,本行的兄弟节点栈没有意义)
}
//遍历完一个字符串,回到根节点
$curNode =$this->tree->first;
}
return $this->tree;
}
//查询是否存在树中
public function search($str){
$curNode = $this->tree;
//如果树还没生成,返回false
if(null == $curNode){
return false;
}
$curNode =$this->tree->first;
//如果树还没生成,返回false
if(null == $curNode){
return false;
}
$isExist = true;
$str .= '$';//拼接上结束符
for($i=0;$i<strlen($str);$i++){
if(null ==$curNode){
$isExist =false;
break;
}
//如果匹配,则查下一个字符
if($str[$i] ==$curNode->symbol){
$curNode =$curNode->first;
continue;
}
//查找兄弟节点
while(null !=$curNode && $str[$i] != $curNode->symbol){
$curNode =$curNode->last;
}
//兄弟节点都没有匹配的,则返回false
if(null ==$curNode){
$isExist =false;
break;
}
//兄弟节点匹配的,查找其子节点
$curNode =$curNode->first;
}
return $isExist;
}
}
$doubleLinkKeyTree= new DoubleLinkKeyTree();
$res =$doubleLinkKeyTree->generate(array('lin', 'php', 'li'));
print_r($res);
——written by linhxx 2017.07.14
相关阅读:
PHP数据结构(十三) ——动态查找表(二叉排序树)
PHP数据结构(十二) ——静态查找表
PHP数据结构(十一) ——图的连通性问题与最小生成树算法(2)
PHP数据结构(十一) ——图的连通性问题与最小生成树算法(1)
PHP数据结构(十) ——有向无环图与拓扑算法
PHP数据结构(九) ——图的定义、存储与两种方式遍历
PHP数据结构(八) ——赫夫曼树实现字符串编解码(实践2)
PHP数据结构(八) ——赫夫曼树实现字符串编解码(实践1)
PHP数据结构(八) ——赫夫曼树实现字符串编解码(理论)
PHP数据结构(七) ——串与实现KMP算法
PHP数据结构(六) ——树与二叉树之概念及存储结构
PHP数据结构(六) ——数组的相乘、广义表
PHP数据结构(五) ——数组的压缩与转置
PHP数据结构(四) ——队列
PHP数据结构(三)——运用栈实现括号匹配
PHP数据结构(二)——链式结构线性表
PHP数据结构(一)——顺序结构线性表
- Python 用OPEN读文件报错 ,路径以及r
- python 如何设置多线程
- R语言读CSV、txt文件方式以及read.table read.csv 和readr(大数据读取包)
- python 多进程设置 整理版本1
- 11g Dataguard中的snapshot standby特性(r8笔记第49天)
- 物化视图刷新结合ADG的尝试 (r8笔记第47天)
- 关于CPU使用率高的awr分析(r8笔记第46天)
- 图形工具和命令行的博弈-swingbench配置(r8笔记第63天)
- 手把手教你用LDA特征选择
- 一个关于执行计划的小问题测试(r8笔记第60天)
- 【Go 语言社区】www.golangweb.com通过工信部审核,正式挂牌社区域名
- golang 算法课程 正式开课--第一季 第1节
- 在 Mac OS X 装不上 TensorFlow?看了这篇就会装
- 利用python内置函数,快速统计单词在文本中出现的次数
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 【LeetCode每日一题】23. Merge k Sorted Lists
- MyBatis Generator( 逆向工程以及源码分析 )
- 虚拟机(Linux)常用命令
- Spring框架
- Servlet技术2
- 你缺的不是天赋,而是亲和度
- TypeScript: 为什么必须学
- 一、环境搭建、以及聊聊更重要的...
- 四、作用域与作用域链
- 【从0到1学算法】递归
- 手把手教你创建 Spring MVC 实例
- 举一反三:三种问题,两个指针,一种方法
- torch.backends.cudnn.benchmark ?!
- jQuery ui中sortable draggable droppable的使用
- 阿里面试:看你springBoot用的比较溜来,说说springboot自动装配是怎么回事?