树结构之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 相关文章推荐
基于jQuery的为attr添加id title等效果的实现代码
Apr 20 Javascript
js模拟点击事件实现代码
Nov 06 Javascript
JQ获取动态加载的图片大小的正确方法分享
Nov 08 Javascript
sliderToggle在写jquery的计时器setTimeouter中不生效
May 26 Javascript
JavaScrip调试技巧之断点调试
Oct 22 Javascript
基于BootStrap实现局部刷新分页实例代码
Aug 08 Javascript
vue增删改查的简单操作
Jul 15 Javascript
BootStrap TreeView使用实例详解
Nov 01 Javascript
Angular 作用域scope的具体使用
Dec 11 Javascript
Vue-Router模式和钩子的用法
Feb 28 Javascript
玩转Koa之koa-router原理解析
Dec 29 Javascript
11个Javascript小技巧帮你提升代码质量(小结)
Dec 28 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
一个简单计数器的源代码
2006/10/09 PHP
在PHP3中实现SESSION的功能(一)
2006/10/09 PHP
php实现无限级分类实现代码(递归方法)
2011/01/01 PHP
PHP求小于1000的所有水仙花数的代码
2012/01/10 PHP
PHP笔记之:基于面向对象设计的详解
2013/05/14 PHP
在PHP模板引擎smarty生成随机数的方法和math函数详解
2014/04/24 PHP
使用Git实现Laravel项目的自动化部署
2019/11/24 PHP
php设计模式之组合模式实例详解【星际争霸游戏案例】
2020/03/27 PHP
js判断游览器类型及版本号的代码
2014/05/11 Javascript
JavaScript实现为指定对象添加多个事件处理程序的方法
2015/04/17 Javascript
Javascript非构造函数的继承
2015/04/27 Javascript
JS实现的网页背景闪电闪烁效果代码
2015/10/17 Javascript
jquery ajax双击div可直接修改div中的内容
2016/03/04 Javascript
详解Angular调试技巧之报错404(not found)
2018/01/31 Javascript
浅谈针对Vue相同路由不同参数的刷新问题
2018/09/29 Javascript
在angularJs中进行数据遍历的2种方法
2018/10/08 Javascript
基于canvasJS在PHP中制作动态图表
2020/05/30 Javascript
一文秒懂nodejs中的异步编程
2021/01/28 NodeJs
[58:21]DOTA2亚洲邀请赛 4.3 突围赛 Liquid vs VGJ.T 第二场
2018/04/04 DOTA
python self,cls,decorator的理解
2009/07/13 Python
python网络编程学习笔记(四):域名系统
2014/06/09 Python
简单介绍Python中的round()方法
2015/05/15 Python
Python实现对excel文件列表值进行统计的方法
2015/07/25 Python
python微信跳一跳游戏辅助代码解析
2018/01/29 Python
对python For 循环的三种遍历方式解析
2019/02/01 Python
python基础教程之while循环
2019/08/14 Python
英国领先的狗和宠物美容专家:Christies Direct
2017/04/03 全球购物
世界上最好的旅行夹克:BauBax
2018/12/23 全球购物
酒店端午节促销方案
2014/02/18 职场文书
请假条格式范文
2014/04/10 职场文书
违章停车检讨书
2014/10/21 职场文书
公司保密管理制度
2015/08/04 职场文书
使用python如何删除同一文件夹下相似的图片
2021/05/07 Python
sql查询结果列拼接成逗号分隔的字符串方法
2021/05/25 SQL Server
基于PyTorch实现一个简单的CNN图像分类器
2021/05/29 Python
python随机打印成绩排名表
2021/06/23 Python