详解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小技巧--自动隐藏红叉叉
Aug 13 Javascript
extjs grid设置某列背景颜色和字体颜色的方法
Sep 03 Javascript
div失去焦点事件实现思路
Apr 22 Javascript
javascript强制点击广告的方法
Feb 06 Javascript
jquery获取复选框checkbox的值的简单实现方法
May 26 Javascript
javascript iframe跨域详解
Oct 26 Javascript
ReactNative实现Toast的示例
Dec 31 Javascript
Vue和React组件之间的传值方式详解
Jan 31 Javascript
基于mpvue搭建微信小程序项目框架的教程详解
Apr 10 Javascript
微信小程序-API接口安全详解
Jul 16 Javascript
详解webpack打包vue项目之后生成的dist文件该怎么启动运行
Sep 06 Javascript
vue 解决数组赋值无法渲染在页面的问题
Oct 28 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
优化使用mysql存储session的php代码
2008/01/10 PHP
php购物车实现代码
2011/10/10 PHP
PHP+Mysql日期时间如何转换(UNIX时间戳和格式化日期)
2012/07/15 PHP
PHP 等比例缩放图片详解及实例代码
2016/09/18 PHP
php实现银联商务公众号+服务窗支付的示例代码
2019/10/12 PHP
THINKPHP5分页数据对象处理过程解析
2020/10/28 PHP
JS+XML 省份和城市之间的联动实现代码
2009/10/14 Javascript
jQuery 白痴级入门教程
2009/11/11 Javascript
jQuery UI Dialog 创建友好的弹出对话框实现代码
2012/04/12 Javascript
解析使用js判断只能输入数字、字母等验证的方法(总结)
2013/05/14 Javascript
nodejs中实现路由功能
2014/12/29 NodeJs
ES6中的数组扩展方法
2016/08/26 Javascript
Javascript基于jQuery UI实现选中区域拖拽效果
2016/11/25 Javascript
JavaScript在form表单中使用button按钮实现submit提交方法
2017/01/23 Javascript
js读取本地文件的实例
2017/12/22 Javascript
layui下拉框获取下拉值(select)的例子
2019/09/10 Javascript
python中readline判断文件读取结束的方法
2014/11/08 Python
Python计算三角函数之asin()方法的使用
2015/05/15 Python
定制FileField中的上传文件名称实例
2017/08/23 Python
Python Cookie 读取和保存方法
2018/12/28 Python
Python一键查找iOS项目中未使用的图片、音频、视频资源
2019/08/12 Python
Pandas DataFrame中的tuple元素遍历的实现
2019/10/23 Python
pycharm新建Vue项目的方法步骤(图文)
2020/03/04 Python
解决python 虚拟环境删除包无法加载的问题
2020/07/13 Python
Pycharm调试程序技巧小结
2020/08/08 Python
清除canvas画布内容(点擦除+线擦除)
2020/08/12 HTML / CSS
学生党员思想汇报
2013/12/28 职场文书
优秀士兵先进事迹
2014/02/06 职场文书
《谁的本领大》教后反思
2014/04/25 职场文书
人事任命书格式
2014/06/05 职场文书
工人先进事迹材料
2014/12/26 职场文书
初中生毕业评语
2014/12/29 职场文书
淮海战役观后感
2015/06/11 职场文书
高中运动会前导词
2015/07/20 职场文书
某某幼儿园的教育教学管理调研分析报告
2019/11/29 职场文书
Python Pandas知识点之缺失值处理详解
2021/05/11 Python