树结构之JavaScript


Posted in Javascript onJanuary 24, 2017

对于数据结构“树”,想必大家都熟悉,今儿,我们就再来回顾一下数据结构中的二叉树与树,并用JavaScript实现它们。

ps:树结构在前端中,很多地方体现得淋漓尽致,如Vue的虚拟DOM以及冒泡等等。

二叉树

--概念--

二叉树是一种树形结构,它的特点是每个结点至多只有两棵子树(即二叉树中不存在度大于2的结点),并且,二叉树的子树有左右之分,其次序不能任意颠倒。

如下,就是一棵二叉树(注:下文二叉树相关例子,都以该二叉树为例):

树结构之JavaScript

且,遍历二叉树(traversing binary tree)有三种常用方式,如下:

1)、先序遍历二叉树 (根左右)  

        若二叉树为空,则空操作;否则

        --访问根结点;

        --先序遍历左子树;

        --先序遍历右子树。

例如,上述例子中的二叉树,遍历结果如下:

树结构之JavaScript

2)、中序遍历二叉树(左根右)

         若二叉树为空,则空操作;否则

         --中序遍历左子树;

         --访问根结点;

         --中序遍历右子树。

例如,上述例子中的二叉树,遍历结果如下:

树结构之JavaScript

3)、后序遍历二叉树(左右根)

        若二叉树为空,则空操作;否则

        --后序遍历左子树;

        --后序遍历右子树;

--访问根结点。

例如,上述例子中的二叉树,遍历结果如下:

树结构之JavaScript

好了,了解了二叉树以及遍历方式,那么,接下来我们就一起用JavaScrip来实现下吧,当然采用链式存储结构。

首先,利用JavaScript构造函数建立二叉树结点,如下:

function TreeNode(){
 this.data = null;//该节点数据
 this.lchild = null;//左子树
 this.rchild = null;//右子树 
};

然后,我们可以通过遍历二叉树的算法,构建一棵二叉树,如下,采用先序序列建立一棵二叉树方法:

/*
*method:采用先序序列建立二叉树
*@params: nodeList(Array) --树节点,以先序序列存入数组中,null代表空节点
*/
TreeNode.createBiTree = function(nodeList){
 var i = 0;
 return (function getNode(){
 var node = null,
 val = nodeList[i++];
 if(!val){
 node = null;
 }else{
 node = new TreeNode();
 node.data = val;
 node.lchild = getNode();
 node.rchild = getNode();
 }
 return node;
 })();
};

最后,就是遍历一棵二叉树咯,分别为先序遍历(PreOrderTraverse)、中序遍历(InOrderTraverse)以及后序遍历(PostOrderTraverse),如下:

TreeNode.prototype = {
 constructor: TreeNode,
 _PreOrderTraverse: function(node){
 if(node){
 console.log(node.data);
 this._PreOrderTraverse(node.lchild);
 this._PreOrderTraverse(node.rchild);
 }
 },
 PreOrderTraverse: function(){
 console.log('PreOrder:');
 this._PreOrderTraverse(this);
 },
 _InOrderTraverse: function(node){
 if(node){
 this._InOrderTraverse(node.lchild);
 console.log(node.data);
 this._InOrderTraverse(node.rchild);
 }
 },
 InOrderTraverse: function(){
 console.log('InOrder:');
 this._InOrderTraverse(this);
 },
 _PostOrderTraverse: function(node){
 if(node){
 this._PostOrderTraverse(node.lchild);
 this._PostOrderTraverse(node.rchild);
 console.log(node.data);
 }
 },
 PostOrderTraverse: function(){
 console.log('PostOrder:');
 this._PostOrderTraverse(this);
 }
};

好了,利用上述二叉树例子,我们可以自行测试下:

var treeNode = null,
 nodeList = ['A', 'B', 'C', null, null, 'D', 'E', null, 'G', null, null, 'F', null, null, null];
//getting a binary tree from nodeList
treeNode = TreeNode.createBiTree(nodeList); 
//traversing the tree of treeNode
treeNode.PreOrderTraverse();//ABCDEGF
treeNode.InOrderTraverse();//CBEGDFA
treeNode.PostOrderTraverse();//CGEFDBA

--概念--

树是n(n>=0)个结点的有限集。在任意一棵非空树中,有且仅有一个特定的称为根(root)的结点,当n>1时,其余结点可分为m(m>0)个互不相交的有限集,其中每个集合本身又是一棵树,称为根的子树。当然,二叉树肯定属于树咯。

如下,就是一棵树(注:下文树的相关例子,都以该树为例):

树结构之JavaScript

,遍历一棵多孩子树,有两种常用遍历方式,如下:

1) 、先根遍历,和深度优先搜索(Depth_First Search)遍历类似。都是利用栈来遍历元素,如下:

树结构之JavaScript

2) 、按层次遍历,和广度优先搜索(Breadth_First Search)遍历类似。都是利用队列来遍历元素,如下:

树结构之JavaScript

好了,了解了树以及遍历方式,那么,接下来我们就一起用JavaScrip来实现下吧,当然也是采用链式存储结构。

首先,利用JavaScript建立树结点,如下:

/*
*@Params: data --节点数据
 children -- 所有孩子结点
*/
function TreeNode(data, children){
 if(!(this instanceof TreeNode)){
 return new TreeNode(data, children); 
 }
 this.data = data || null;
 this.children = children || [];
};

根据上述TreeNode构造函数,我们可以将例子中的树,表示如下:

var treeNode = TreeNode('A', [
 TreeNode('B', [TreeNode('E')]),
 TreeNode('C'),
 TreeNode('D')
 ]);

接着,就是编写遍历树方法咯,分别为先根遍历和按层次遍历,如下:

TreeNode.prototype = {
 constructor: TreeNode,
 _traverseAsDFS: function(node){//先根遍历
 var self = this;
 if(node){
 console.log(node.data);
 node.children.forEach(function(child){
 if(child.children.length){
 self._traverseAsDFS(child);
 }else{
 console.log(child.data);
 }
 });
 } 
 },
 traverseAsDFS: function(){
 console.log('Depth_First Search');
 this._traverseAsDFS(this); 
 },
 traverseAsBFS: function(){//按层次遍历
 var queue = [];
 console.log('Breadth_First Search');
 console.log(this.data);
 if(this.children.length){
 queue.push(this);
 }
 while(queue.length){
 let tempNode = queue.shift();
 tempNode.children.forEach(function(child){
 console.log(child.data);
 if(child.children.length){
 queue.push(child);
 } 
 });
 }
 }
};

好了,利用上述二叉树例子,我们可以自行测试下:

var treeNode = TreeNode('A', [
 TreeNode('B', [TreeNode('E')]),
 TreeNode('C'),
 TreeNode('D')
 ]);
treeNode.traverseAsDFS();//ABECD
treeNode.traverseAsBFS();//ABCDE

关于上述全部代码,见github。

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持三水点靠木!

Javascript 相关文章推荐
JS中setTimeout()的用法详解
Apr 14 Javascript
animate 实现滑动切换效果【实例代码】
May 05 Javascript
Bootstrap框架动态生成Web页面文章内目录的方法
May 12 Javascript
Vue.js报错Failed to resolve filter问题的解决方法
May 25 Javascript
Javascript中级语法快速入手
Jul 30 Javascript
微信小程序picker组件简单用法示例【附demo源码下载】
Dec 05 Javascript
理解Koa2中的async&await的用法
Feb 05 Javascript
Vue2.0+Vux搭建一个完整的移动webApp项目的示例
Mar 19 Javascript
vue实现文字加密功能
Sep 27 Javascript
js实现双人五子棋小游戏
May 28 Javascript
JS实现电脑虚拟键盘的操作
Jun 24 Javascript
微信小程序实现登录注册功能
Dec 29 Javascript
AngularJS实现使用路由切换视图的方法
Jan 24 #Javascript
javascript 正则表达式去空行方法
Jan 24 #Javascript
JavaScript中动态向表格添加数据
Jan 24 #Javascript
微信小程序开发的四十个技术窍门总结(推荐)
Jan 23 #Javascript
ajax分页效果(bootstrap模态框)
Jan 23 #Javascript
jquery easyui DataGrid简单示例
Jan 23 #Javascript
浅谈javascript的闭包
Jan 23 #Javascript
You might like
PHP中使用CURL模拟登录并获取数据实例
2014/07/01 PHP
ThinkPHP单字母函数(快捷方法)使用总结
2014/07/23 PHP
php+mysqli实现批量执行插入、更新及删除数据的方法
2015/01/29 PHP
微信公众平台开发教程⑥ 微信开发集成类的使用图文详解
2019/04/10 PHP
jQuery 表单验证扩展代码(一)
2010/10/11 Javascript
禁止页面刷新让F5快捷键及右键都无效
2014/01/22 Javascript
js实现的捐赠管理完整实例
2015/01/20 Javascript
javascript中FOREACH数组方法使用示例
2016/03/01 Javascript
B/S(Web)实时通讯解决方案分享
2017/04/06 Javascript
jQuery实现拖动效果的实例代码
2017/06/25 jQuery
微信小程序实现图片放大预览功能
2020/10/22 Javascript
linux 后台运行node服务指令方法
2018/05/23 Javascript
mpvue小程序循环动画开启暂停的实现方法
2019/05/15 Javascript
详解Vue.js中引入图片路径的几种方式
2019/06/17 Javascript
js实现多张图片每隔一秒切换一张图片
2019/07/29 Javascript
12 种使用Vue 的最佳做法
2020/03/30 Javascript
如何在vue中使用jointjs过程解析
2020/05/29 Javascript
请求时token过期自动刷新token操作
2020/09/11 Javascript
python实现ipsec开权限实例
2014/11/11 Python
python结合opencv实现人脸检测与跟踪
2015/06/08 Python
Python面向对象编程基础解析(二)
2017/10/26 Python
python矩阵转换为一维数组的实例
2018/06/05 Python
python 执行文件时额外参数获取的实例
2018/12/18 Python
在Python中关于使用os模块遍历目录的实现方法
2019/01/03 Python
纯CSS绘制漂亮的圆形图案效果
2014/05/07 HTML / CSS
CSS3中animation实现流光按钮效果
2020/12/21 HTML / CSS
J.Crew官网:美国知名休闲服装品牌
2017/05/19 全球购物
Math.round(11.5)等於多少? Math.round(-11.5)等於多少?
2015/01/27 面试题
商务英语专业毕业生自荐信
2013/11/05 职场文书
传媒专业推荐信范文
2013/11/23 职场文书
学校四群教育实施方案
2014/06/12 职场文书
离婚协议书包括哪些内容
2014/10/16 职场文书
个人政治思想总结
2015/03/05 职场文书
新年祝酒词大全
2015/08/11 职场文书
nginx 反向代理之 proxy_pass的实现
2021/03/31 Servers
mysql 体系结构和存储引擎介绍
2022/05/06 MySQL