详解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 相关文章推荐
js去空格技巧分别去字符串前后、左右空格
Oct 21 Javascript
js获取当前月的第一天和最后一天的小例子
Nov 18 Javascript
js中function()使用方法
Dec 24 Javascript
Bootstrap项目实战之子栏目资讯内容
Apr 25 Javascript
node中koa中间件机制详解
Aug 22 Javascript
javascript基础进阶_深入剖析执行环境及作用域链
Sep 05 Javascript
javascript中的replace函数(带注释demo)
Jan 07 Javascript
JS使用setInterval实现的简单计时器功能示例
Apr 19 Javascript
Vue 中的受控与非受控组件的实现
Dec 17 Javascript
微信小程序实现订单倒计时
Nov 01 Javascript
使用 node.js 模仿 Apache 小部分功能
Jul 07 Javascript
vue项目初始化到登录login页面的示例
Oct 31 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
深入探讨<br />和 \r\n两者有什么区别??
2013/06/05 PHP
php之CodeIgniter学习笔记
2013/06/17 PHP
php自定义session示例分享
2014/04/22 PHP
phpQuery让php处理html代码像jQuery一样方便
2015/01/06 PHP
PHP模拟QQ登录的方法
2015/07/29 PHP
PHP编写简单的App接口
2016/08/28 PHP
40款非常棒的jQuery 插件和制作教程(系列二)
2011/11/02 Javascript
网页中可关闭的漂浮窗口实现可自行调节
2013/08/20 Javascript
JavaScript中5种调用函数的方法
2015/03/12 Javascript
javascript通过获取html标签属性class实现多选项卡的方法
2015/07/27 Javascript
Bootstrap modal使用及点击外部不消失的解决方法
2016/12/13 Javascript
ES6学习之变量的两种命名方法示例
2017/07/18 Javascript
EasyUI创建人员树的实例代码
2017/09/15 Javascript
vue中如何去掉空格的方法实现
2018/11/09 Javascript
Angular刷新当前页面的实现方法
2018/11/21 Javascript
7个好用的JavaScript技巧分享(译)
2019/05/07 Javascript
深入学习JavaScript中的bom
2019/05/27 Javascript
vue实现滑动超出指定距离回顶部功能
2019/07/31 Javascript
vue项目中使用vue-layer弹框插件的方法
2020/03/11 Javascript
详解webpack的文件监听实现(热更新)
2020/09/11 Javascript
[02:26]2016国际邀请赛8月3日开战 中国军团出征西雅图
2016/08/02 DOTA
Python多线程、异步+多进程爬虫实现代码
2016/02/17 Python
Python实现快速傅里叶变换的方法(FFT)
2018/07/21 Python
pandas 数据归一化以及行删除例程的方法
2018/11/10 Python
python tkinter组件使用详解
2019/09/16 Python
python 单线程和异步协程工作方式解析
2019/09/28 Python
python3中的eval和exec的区别与联系
2019/10/10 Python
PyQt使用QPropertyAnimation开发简单动画
2020/04/02 Python
Elemis美国官网:英国的第一豪华护肤品牌
2018/03/15 全球购物
C#里面如何倒序排列一个数组的元素?
2013/06/21 面试题
js正则匹配markdown里的图片标签的实现
2021/03/24 Javascript
安全生产月活动总结
2014/05/04 职场文书
落实八项规定专题民主生活会对照检查材料
2014/09/15 职场文书
2014购房个人委托书范本
2014/10/12 职场文书
2014年最新版离婚协议书范本
2014/11/25 职场文书
公司承诺书格式范文
2015/04/28 职场文书