详解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 相关文章推荐
基于jQuery实现表格数据的动态添加与统计的代码
Jan 31 Javascript
js下拉框二级关联菜单效果代码具体实现
Aug 03 Javascript
Jquery中val()表单取值赋值的实例代码
Aug 15 Javascript
js Math 对象的方法
Sep 01 Javascript
JS如何将数字类型转化为没3个一个逗号的金钱格式
Jan 27 Javascript
Jquery 获取指定标签的对象及属性的设置与移除
May 29 Javascript
一个获取第n个元素节点的js函数
Sep 02 Javascript
js分页工具实例
Jan 28 Javascript
fastclick插件导致日期(input[type="date"])控件无法被触发该如何解决
Nov 09 Javascript
JavaScript动态检验密码强度的实现方法
Nov 09 Javascript
Vue 之孙组件向爷组件通信的实现
Apr 23 Javascript
JS使用new操作符创建对象的方法分析
May 30 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
DC游戏Steam周三特惠 《蝙蝠侠》阿卡姆系列平史低
2020/04/09 欧美动漫
PHP 身份验证方面的函数
2009/10/11 PHP
PHP网站备份程序代码分享
2011/06/10 PHP
PHP stripos()函数及注意事项的分析
2013/06/08 PHP
php网页病毒清除类
2014/12/08 PHP
简单的自定义php模板引擎
2016/08/26 PHP
PHP实现的方程求解示例分析
2016/11/11 PHP
效率高的Javscript字符串替换函数的benchmark
2008/08/02 Javascript
JQuery团队打造的javascript单元测试工具QUnit介绍
2010/02/26 Javascript
javascript各浏览器中option元素的表现差异
2011/04/07 Javascript
js格式化货币数据实现代码
2013/09/04 Javascript
jQuery中replaceWith()方法用法实例
2014/12/25 Javascript
简单模拟node.js中require的加载机制
2016/10/27 Javascript
浅谈键盘上回车按钮的js触发事件
2017/02/13 Javascript
JS实现本地存储信息的方法(基于localStorage与userData)
2017/02/18 Javascript
详解axios在node.js中的post使用
2017/04/27 Javascript
python代码检查工具pylint 让你的python更规范
2012/09/05 Python
python模拟登陆阿里妈妈生成商品推广链接
2014/04/03 Python
Python深入06——python的内存管理详解
2016/12/07 Python
Python 出现错误TypeError: ‘NoneType’ object is not iterable解决办法
2017/01/12 Python
python中将函数赋值给变量时需要注意的一些问题
2017/08/18 Python
Python测试模块doctest使用解析
2019/08/10 Python
python多线程扫描端口(线程池)
2019/09/04 Python
python 实现在无序数组中找到中位数方法
2020/03/03 Python
jupyter notebook 参数传递给shell命令行实例
2020/04/10 Python
Python+PyQt5+MySQL实现天气管理系统
2020/06/16 Python
基于Python的一个自动录入表格的小程序
2020/08/05 Python
python实现AdaBoost算法的示例
2020/10/03 Python
adidas官方旗舰店:德国运动用品制造商
2017/11/25 全球购物
德国在线购买葡萄酒网站:Geile Weine
2019/09/24 全球购物
Jacques Lemans德国:奥地利钟表品牌
2019/12/26 全球购物
村庄环境整治方案
2014/05/15 职场文书
运动会广播稿150字(9篇)
2014/09/20 职场文书
四风问题班子对照检查材料
2014/09/27 职场文书
使用Springboot实现健身房管理系统
2021/07/01 Java/Android
Python多个MP4合成视频的实现方法
2021/07/16 Python