树结构之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 相关文章推荐
Mootools 1.2教程(21)——类(二)
Sep 15 Javascript
JQuery datepicker 使用方法
May 20 Javascript
node.js中的forEach()是同步还是异步呢
Jan 29 Javascript
jQuery+Ajax实现限制查询间隔的方法
Jun 07 Javascript
详解Javascript中prototype属性(推荐)
Sep 03 Javascript
jQuery中页面返回顶部的方法总结
Dec 30 Javascript
JS验证input输入框(字母,数字,符号,中文)
Mar 23 Javascript
vue实现密码显示隐藏切换功能
Feb 23 Javascript
vue.js实现数据库的JSON数据输出渲染到html页面功能示例
Aug 03 Javascript
react native 仿微信聊天室实例代码
Sep 17 Javascript
layui.tree组件的使用以及搜索节点功能的实现
Sep 26 Javascript
Vue-cli assets SubDirectory及PublicPath区别详解
Aug 18 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-redis中的sort排序函数总结
2015/07/08 PHP
PHP闭包函数传参及使用外部变量的方法
2016/03/15 PHP
ThinkPHP中limit()使用方法详解
2016/04/19 PHP
JSON 客户端和服务器端的格式转换
2009/08/27 Javascript
javascript 按回车键相应按钮提交事件
2009/11/02 Javascript
js获取location.href的参数实例代码
2013/08/02 Javascript
jquery indexOf使用方法
2013/08/19 Javascript
jquery让返回的内容显示在特定div里(代码少而精悍)
2014/06/23 Javascript
JS函数this的用法实例分析
2015/02/05 Javascript
jQuery实现带分组数据的Table表头排序实例分析
2015/11/24 Javascript
AngularJS整合Springmvc、Spring、Mybatis搭建开发环境
2016/02/25 Javascript
vue.js实现刷新当前页面的方法教程
2017/07/05 Javascript
JavaScript实现简单评论功能
2017/08/17 Javascript
Three.js利用Detector.js插件如何实现兼容性检测详解
2017/09/26 Javascript
vue axios 简单封装以及思考
2018/10/09 Javascript
Vue 微信端扫描二维码苹果端却只能保存图片问题(解决方法)
2020/01/19 Javascript
JavaScript实现横版菜单栏
2020/03/17 Javascript
Python多线程学习资料
2012/12/19 Python
Python内置函数bin() oct()等实现进制转换
2012/12/30 Python
仅利用30行Python代码来展示X算法
2015/04/01 Python
Python的Django框架中forms表单类的使用方法详解
2016/06/21 Python
基于asyncio 异步协程框架实现收集B站直播弹幕
2016/09/11 Python
python GUI图形化编程wxpython的使用
2019/07/19 Python
python通过robert、sobel、Laplace算子实现图像边缘提取详解
2019/08/21 Python
python爬虫增加访问量的方法
2019/08/22 Python
Python timeit模块的使用实践
2020/01/13 Python
jupyter notebook tensorflow打印device信息实例
2020/04/20 Python
CSS3实现多重边框的方法总结
2016/05/31 HTML / CSS
详解CSS3弹性伸缩盒
2020/09/21 HTML / CSS
Html5 实现微信分享及自定义内容的流程
2019/08/20 HTML / CSS
HTML5手指下滑弹出负一屏阻止移动端浏览器内置下拉刷新功能的实现代码
2020/04/10 HTML / CSS
台湾良兴购物网:EcLife
2019/12/01 全球购物
小学安全汇报材料
2014/08/14 职场文书
小学教师求职信范文
2015/03/20 职场文书
十八大观后感
2015/06/12 职场文书
MySQL RC事务隔离的实现
2022/03/31 MySQL