javascript实现数据结构:线索二叉树
遍历二叉树是按一定的规则将树中的结点排列成一个线性序列,即是对非线性结构的线性化操作。如何找到遍历过程中动态得到的每个结点的直接前驱和直接后继(第一个和最后一个除外)?如何保存这些信息?
设一棵二叉树有n个结点,则有n-1条边(指针连线) , 而n个结点共有2n个指针域(Lchild和Rchild) ,显然有n+1个空闲指针域未用。则可以利用这些空闲的指针域来存放结点的直接前驱和直接后继信息。
对结点的指针域做如下规定:
1.若结点有左子树,则其leftChild域指示其左孩子,否则令leftChild域指示其前驱。
2.若结点有右子树,则其rightChild域指示其右孩子,否则令其rightChild域指示其后继。
为了避免混淆,尚需改变结点结构,增加两个标志域(leftTag, rightTag),其中:
-- 0 leftChild域指示结点的左孩子
leftTag --
-- 1 rightChild域指示结点的前驱
-- 0 rightChild域指示结点的右孩子
rightTag --
-- 1 rightChild域指示结点的后继
以这种结点结构构成的二叉链表作为二叉树的存储结构,叫做线索链表,其中指向结点前驱和后继的指针,叫做线索。
加上线索的二叉树称之为线索二叉树(Threaded Binary Tree)。
对二叉树以某种次序遍历使其变为线索二叉树的过程叫做线索化。
说明:画线索二叉树时,实线表示指针,指向其左、右孩子;虚线表示线索,指向其直接前驱或直接后继。
在线索树上进行遍历,只要先找到序列中的第一个结点,然后就可以依次找结点的直接后继结点直到后继为空为止。
如何在线索树中找结点的直接后继?
以图(d) ,(e)所示的中序线索树为例:
◆ 树中所有叶子结点的右链都是线索。右链直接指示了结点的直接后继,如结点G的直接后继是结点E。
◆ 树中所有非叶子结点的右链都是指针。根据中序遍历的规律,非叶子结点的直接后继是遍历其右子树时访问的第一个结点,即右子树中最左下的(叶子)结点。如结点C的直接后继:沿右指针找到右子树的根结点F,然后沿左链往下直到Ltag=1的结点即为C的直接后继结点H。
如何在线索树中找结点的直接前驱?
若结点的Ltag=1,则左链是线索,指示其直接前驱;否则,遍历左子树时访问的最后一个结点(即沿左子树中最右往下的结点) 为其直接前驱结点。
对于后序遍历的线索树中找结点的直接后继比较复杂,可分以下三种情况:
◆ 若结点是二叉树的根结点:其直接后继为空;
◆ 若结点是其父结点的左孩子或右孩子且其父结点没有右子树:直接后继为其父结点;
◆ 若结点是其父结点的左孩子且其父结点有右子树:直接后继是对其父结点的右子树按后序遍历的第一个结点。
线索化二叉树
二叉树的线索化指的是依照某种遍历次序使二叉树成为线索二叉树的过程。
线索化的过程就是在遍历过程中修改空指针使其指向直接前驱或直接后继的过程。
仿照线性表的存储结构,在二叉树的线索链表上也添加一个头结点head,头结点的指针域的安排是:
◆ Lchild域:指向二叉树的根结点;
◆ Rchild域:指向中序遍历时的最后一个结点;
◆ 二叉树中序序列中的第一个结点Lchild指针域和最后一个结点Rchild指针域均指向头结点head。
如同为二叉树建立了一个双向线索链表,对一棵线索二叉树既可从头结点也可从最后一个结点开始按寻找直接后继进行遍历。显然,这种遍历不需要堆栈。
线索二叉树的遍历
在线索二叉树中,由于有线索存在,在某些情况下可以方便地找到指定结点在某种遍历序列中的直接前驱或直接后继。此外,在线索二叉树上进行某种遍历比在一般的二叉树上进行这种遍历要容易得多,不需要设置堆栈,且算法十分简洁。
线索二叉树的相关代码实现:
var LINK = 0;
var THREAD = 1; function BinaryThreadTree_inOrder(data, leftChild, rightChild) {
this.data = data;
this.leftChild = leftChild || null;
this.rightChild = rightChild || null;
// 左右标记
this.leftTag = this.rightTag = undefined;
}
BinaryThreadTree_inOrder.prototype = {
constructor: BinaryThreadTree_inOrder,
// 中序线索二叉树的遍历
inOrderTraverse_thread: function (visit) {
var p = this.leftChild; while (p != this) {
while (p.leftTag === LINK) p = p.leftChild; if (visit(p.data) === false) return; while (p.rightTag == THREAD && p.rightChild != this) {
p = p.rightChild;
visit(p.data);
}
p = p.rightChild;
}
},
// 中序线索化
inOrderThreading: function () {
return inOrderThreading(this);
},
// 在当前结点插入子树x,p代表当前结点
insertSubTree: function (xTree) {
var s, q;
// x作为p的左子树
if (this.leftTag === THREAD) {
s = this.leftChild; // s为p的前驱
this.leftTag = LINK;
this.leftChild = xTree;
q = xTree; while (q.leftChild && q.leftTag === LINK) q = q.leftChild;
// 找到子树中的最左结点,并修改其前驱指向s
q.leftChild = s;
xTree.rightTag = THREAD;
// x的后继指向p
xTree.rightChild = this;
}
// x作为p的右子树
else if (this.rightTag === THREAD) {
// s为p的后继
s = this.rightChild;
this.rightTag = LINK;
this.rightChild = xTree;
q = xTree; while (q.leftChild && q.leftTag === LINK) q = q.leftChild;
// 找到子树中的最左结点,并修改其前驱指向p
q.leftChild = this;
xTree.rightTag = THREAD;
// x的后继指向p的后继
xTree.rightChild = s;
}
// x作为p的左子树,p的左子树作为x的右子树
else {
s = this.leftChild;
var t = s; while (t.leftChild && t.leftTag === LINK) t = t.leftChild;
// 找到p的左子树的最左结点t和前驱u
var u = t.leftChild;
this.leftChild = xTree;
xTree.rightTag = LINK;
// x作为p的左子树,p的左子树作为x的右子树
xTree.rightChild = s;
t.leftChild = xTree;
q = xTree; while (q.leftChild && q.leftTag === LINK) q = q.leftChild;
// 找到子树中的最左结点,并修改其前驱指向u
q.leftChild = u;
}
}
}; // 二叉树中序线索化
function inOrderThreading(tree) {
var threadTree = new BinaryThreadTree();
threadTree.leftTag = LINK;
threadTree.rightTag = THREAD;
// 右指针回指
threadTree.rightChild = threadTree; var pre;
// 若二叉树为空,左指针回指
if (!tree) threadTree.leftChild = threadTree;
else {
threadTree.leftChild = tree;
pre = threadTree;
inThreading(tree); // 中序遍历进行中序线索化
// 最后一个结点线索化
pre.rightChild = threadTree;
pre.rightTag = THREAD;
threadTree.rightChild = pre;
} return threadTree; function inThreading(p) {
if (!p) return; inThreading(p.leftChild); // 左子树线索化
// 前驱线索
if (!p.leftChild) {
p.leftTag = THREAD;
p.leftChild = pre;
}
// 后继线索
if (!pre.rightChild) {
pre.rightTag = THREAD;
pre.rightChild = p;
}
pre = p;
inThreading(p.rightChild); // 右子树线索化
}
}
javascript实现数据结构:线索二叉树的更多相关文章
- 数据结构《9》----Threaded Binary Tree 线索二叉树
对于任意一棵节点数为 n 的二叉树,NULL 指针的数目为 n+1 , 线索树就是利用这些 "浪费" 了的指针的数据结构. Definition: "A binary ...
- 【Java】 大话数据结构(9) 树(二叉树、线索二叉树)
本文根据<大话数据结构>一书,对Java版的二叉树.线索二叉树进行了一定程度的实现. 另: 二叉排序树(二叉搜索树) 平衡二叉树(AVL树) 二叉树的性质 性质1:二叉树第i层上的结点数目 ...
- 数据结构之线索二叉树——C语言实现
线索二叉树操作 (1) 线索二叉树的表示:将每个节点中为空的做指针与右指针分别用于指针节点的前驱和后续,即可得到线索二叉树. (2) 分类:先序线索二叉树,中序线索二叉树,后续线索二叉树 (3) 增 ...
- 【PHP数据结构】完全二叉树、线索二叉树及树的顺序存储结构
在上篇文章中,我们学习了二叉树的基本链式结构以及建树和遍历相关的操作.今天我们学习的则是一些二叉树相关的概念以及二叉树的一种变形形式. 完全二叉树 什么叫完全二叉树呢?在说到完全二叉树之前,我们先说另 ...
- 数据结构之---C语言实现线索二叉树
//线索二叉树,这里在二叉树的基础上增加了线索化 //杨鑫 #include <stdio.h> #include <stdlib.h> typedef char ElemTy ...
- 数据结构之二叉树篇卷四 -- 二叉树线索化(With Java)
一.线索二叉树简介 二叉树本身是一种非线性结构,然而当你对二叉树进行遍历时,你会发现遍历结果是一个线性序列.这个序列中的节点存在前驱后继关系.因此,如何将这种前驱后继信息赋予给原本的二叉树呢?这就是二 ...
- 一步一步写数据结构(二叉树的建立和遍历,c++)
简述: 二叉树是十分重要的数据结构,主要用来存放数据,并且方便查找等操作,在很多地方有广泛的应用. 二叉树有很多种类,比如线索二叉树,二叉排序树,平衡二叉树等,本文写的是最基础最简单的二叉树. 思路: ...
- 线索二叉树的理解和实现(Java)
线索二叉树的基本概念 我们按某种方式对二叉树进行遍历,将二叉树中所有节点排序为一个线性序列,在该序列中,除第一个结点外每个结点有且仅有一个直接前驱结点:除最后一个结点外每一个结点有且仅有一个直接后继结 ...
- [线索二叉树] [LeetCode] 不需要栈或者别的辅助空间,完成二叉树的中序遍历。题:Recover Binary Search Tree,Binary Tree Inorder Traversal
既上篇关于二叉搜索树的文章后,这篇文章介绍一种针对二叉树的新的中序遍历方式,它的特点是不需要递归或者使用栈,而是纯粹使用循环的方式,完成中序遍历. 线索二叉树介绍 首先我们引入“线索二叉树”的概念: ...
随机推荐
- LINUX下PHP安装VLD扩展并测试OK
首先下载安装vld压缩包,下载前一定注意区分压缩包版本和php版本是否匹配,否则很可能后面make install 失败. //下载安装包—暂时以14版本为例 wget http://pecl.php ...
- HTML5 indexedDb 数据库
indexedDb 数据库 上一节中,我们知道了,HMTL5中内置了两种本地数据库,一种是通过SQL语言来访问的文件型SQL数据库被称为“SQLLite,另一种是是被称为indexedDB 的数据 ...
- centos配置免密登录
一.准备工作 1.先准备两台centos机器.例如:192.168.1.100和192.168.1.101两台机器,配置101免密登录100 2.默认centos会自带ssh和stfp,机器未安装,请 ...
- 把display 属性改为block样式变化问题
可能的值 值 描述 none 此元素不会被显示. block 此元素将显示为块级元素,此元素前后会带有换行符. inline 默认.此元素会被显示为内联元素,元素前后没有换行符. inline-blo ...
- 配置YOLO2(ubuntu16.04+cuda8.0+opencv3.1.0)
要求已经安装好了CUDA 8.0 以及OpenCV3.1.0 YOLO官方网站 配置darknet git clone https://github.com/pjreddie/darknet cd d ...
- 【总结】kali(amd64)中安装nessus
下载nessus: http://www.tenable.com/products/nessus/select-your-operating-system 注册nessus家庭版 http://www ...
- [jQuery] 在线引用地址
百度静态资源公共库: http://libs.baidu.com/jquery/1.9.1/jquery.js jQuery网站: http://code.jquery.com/jquery-1.9. ...
- APP在实际开发中应注意的关键点
在APP开发过程中,开发者比较注重的是功能模块的实现,从而忽略了APP的设计问题,特别是企业开发APP,但是,APP设计是APP开发中非常重要的一个环节,APP界面设计直接影响到APP用户的感官,因此 ...
- keepalived+lvs简单实现
一,部署实战环节 01,服务架构图: 服务器镜像为centos6.9 02,服务安装: 10.0.0.10: 下载keeplived官方包--> http://www.keepalived. ...
- NFS 网络文件系统
1, NFS存储服务概念介绍 NFS是Network File System的缩写,中文意思是网络文件系统, 它的主要功能是通过网络(一般是局域网)让不同的主机系统之间可以共享文件或目录 ...