树结构之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 相关文章推荐
JavaScript的变量作用域深入理解
Oct 25 Javascript
一些有用的JavaScript和jQuery的片段分享
Aug 23 Javascript
JavaScript根据数据生成百分比图和柱状图的实例代码
Jul 14 Javascript
FF(火狐)浏览器无法执行window.close()解决方案
Nov 13 Javascript
js实现iGoogleDivDrag模块拖动层拖动特效的方法
Mar 04 Javascript
实践中学习AngularJS表单
Mar 21 Javascript
javascript实现简单的可随机变色网页计算器示例
Dec 30 Javascript
jQuery实现倒计时重新发送短信验证码功能示例
Jan 12 Javascript
jQuery 判断元素整理汇总
Feb 28 Javascript
jQuery插件FusionCharts绘制的3D饼状图效果实例【附demo源码下载】
Mar 03 Javascript
JavaScript查看代码运行效率console.time()与console.timeEnd()用法
Jan 18 Javascript
微信小程序点击按钮动态切换input的disabled禁用/启用状态功能
Mar 07 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
从网上搜到的phpwind 0day的代码
2006/12/07 PHP
thinkphp视图模型查询提示ERR: 1146:Table 'db.pr_order_view' doesn't exist的解决方法
2014/10/30 PHP
源码分析 Laravel 重复执行同一个队列任务的原因
2017/12/25 PHP
PHP实现简单的协程任务调度demo示例
2020/02/01 PHP
PHP设计模式入门之迭代器模式原理与实现方法分析
2020/04/26 PHP
ECMAScript5(ES5)中bind方法使用小结
2015/05/07 Javascript
基于jQuery+JSON的省市二三级联动效果
2015/06/05 Javascript
jQuery实现向下滑出的二级菜单效果实例
2015/08/22 Javascript
js控住DOM实现发布微博效果
2016/08/30 Javascript
node.js文件上传处理示例
2016/10/27 Javascript
AngularJS的ng Http Request与response格式转换方法
2016/11/07 Javascript
原生JS实现图片轮播切换效果
2016/12/15 Javascript
使用get方式提交表单在地址栏里面不显示提交信息
2017/02/21 Javascript
js eval函数使用,js对象和字符串互转实例
2017/03/06 Javascript
validationEngine 表单验证插件使用实例代码
2017/06/15 Javascript
Bootstrap按钮组实例详解
2017/07/03 Javascript
详解如何在angular2中获取节点
2017/11/23 Javascript
vue中的数据绑定原理的实现
2018/07/02 Javascript
原生JS实现的简单小钟表功能示例
2018/08/30 Javascript
详解微信小程序框架wepy踩坑记录(与vue对比)
2019/03/12 Javascript
微信小程序wxml列表渲染原理解析
2019/11/27 Javascript
vue+element 实现商城主题开发的示例代码
2020/03/26 Javascript
vant 时间选择器--开始时间和结束时间实例
2020/11/04 Javascript
压缩包密码破解示例分享(类似典破解)
2014/01/17 Python
python解析html开发库pyquery使用方法
2014/02/07 Python
Django网络框架之创建虚拟开发环境操作示例
2019/06/06 Python
python 求某条线上特定x值或y值的点坐标方法
2019/07/09 Python
python实现tail -f 功能
2020/01/17 Python
tensorflow实现读取模型中保存的值 tf.train.NewCheckpointReader
2020/02/10 Python
浅谈django不使用restframework自定义接口与使用的区别
2020/07/15 Python
CSS改变网页中鼠标选中文字背景颜色例子
2014/04/23 HTML / CSS
Spartoo英国:欧洲最大的网上鞋店
2016/09/13 全球购物
大学生工作推荐信范文
2013/12/02 职场文书
机关出纳岗位职责
2014/04/03 职场文书
项目投资意向书范本
2015/05/09 职场文书
win7配置本地ftp服务器的图文教程
2022/08/05 Servers