详解JavaScript树结构


Posted in Javascript onJanuary 09, 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 相关文章推荐
我遇到的参数传递中 双引号单引号嵌套问题
Feb 11 Javascript
改进UCHOME的记录发布,增强可访问性用户体验
Jan 17 Javascript
JavaScript继承基础讲解(原型链、借用构造函数、混合模式、原型式继承、寄生式继承、寄生组合式继承)
Aug 16 Javascript
javascript将DOM节点添加到文档的方法实例分析
Aug 04 Javascript
jQuery EasyUI实现右键菜单变灰不可用效果
Sep 24 Javascript
javaScript之split与join的区别(详解)
Nov 08 Javascript
Vue代码分割懒加载的实现方法
Nov 23 Javascript
Mac下安装vue
Apr 11 Javascript
Angular项目如何升级至Angular6步骤全纪录
Sep 03 Javascript
vuex直接赋值的三种方法总结
Sep 16 Javascript
使用JavaScript破解web
Sep 28 Javascript
vue+node 实现视频在线播放的实例代码
Oct 19 Javascript
angular分页指令操作
Jan 09 #Javascript
jquery.zclip轻量级复制失效问题
Jan 08 #Javascript
JavaScript & jQuery完美判断图片是否加载完毕
Jan 08 #Javascript
纯javaScript、jQuery实现个性化图片轮播【推荐】
Jan 08 #Javascript
js实现选项卡内容切换以及折叠和展开效果【推荐】
Jan 08 #Javascript
Javascript 实现计算器时间功能详解及实例(二)
Jan 08 #Javascript
JS 实现计算器详解及实例代码(一)
Jan 08 #Javascript
You might like
php设计模式 Visitor 访问者模式
2011/06/28 PHP
初步介绍PHP扩展开发经验分享
2012/09/06 PHP
php基于socket实现SMTP发送邮件的方法
2015/03/05 PHP
Yii框架的redis命令使用方法简单示例
2019/10/15 PHP
浅谈laravel-admin form中的数据,在提交后,保存前,获取并进行编辑
2019/10/21 PHP
Javascript 中 null、NaN和undefined的区别总结
2013/04/10 Javascript
javascript学习笔记(八)正则表达式
2014/10/08 Javascript
jQuery多媒体插件jQuery Media Plugin使用详解
2014/12/19 Javascript
JavaScript实现点击按钮复制指定区域文本(推荐)
2016/11/25 Javascript
JavaScript获取短信验证码(周期性)
2016/12/29 Javascript
js中删除数组中的某一元素实例(无下标时)
2017/02/28 Javascript
jQuery实现倒计时功能 jQuery实现计时器功能
2017/09/19 jQuery
webpack4之SplitChunksPlugin使用指南
2018/06/12 Javascript
JS实现的JSON序列化操作简单示例
2018/07/02 Javascript
微信小程序多音频播放进度条问题
2018/08/28 Javascript
vue实现与安卓、IOS交互的方法
2018/11/02 Javascript
通过npm或yarn自动生成vue组件的方法示例
2019/02/12 Javascript
js中console在一行内打印字符串和对象的方法
2019/09/10 Javascript
如何换个角度使用VUE过滤器详解
2019/09/11 Javascript
Python实现扫描指定目录下的子目录及文件的方法
2014/07/16 Python
安装Python的web.py框架并从hello world开始编程
2015/04/25 Python
用Python写冒泡排序代码
2016/04/12 Python
python 系统调用的实例详解
2017/07/11 Python
Python自动化运维_文件内容差异对比分析
2017/12/13 Python
python 类对象和实例对象动态添加方法(分享)
2017/12/31 Python
python生成带有表格的图片实例
2019/02/03 Python
Python批量生成幻影坦克图片实例代码
2019/06/04 Python
NYX Professional Makeup俄罗斯官网:世界知名的化妆品品牌
2019/12/26 全球购物
班主任班级寄语大全
2014/04/04 职场文书
《小动物过冬》教学反思
2014/04/17 职场文书
网络技术专业求职信
2014/05/02 职场文书
抗洪救灾先进集体事迹材料
2014/05/26 职场文书
交通事故委托书范本(2篇)
2014/09/21 职场文书
群众路线批评与自我批评发言稿
2014/10/16 职场文书
python opencv旋转图片的使用方法
2021/06/04 Python
Vue elementUI表单嵌套表格并对每行进行校验详解
2022/02/18 Vue.js