树结构之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 相关文章推荐
Javascript Select操作大集合
May 26 Javascript
动态加载图片路径 保持JavaScript控件的相对独立性
Sep 06 Javascript
JavaScript移除数组元素减少长度的方法
Sep 05 Javascript
JavaScript中prototype为对象添加属性的误区介绍
Oct 15 Javascript
jQuery之字体大小的设置方法
Feb 27 Javascript
JS实现的用来对比两个用指定分隔符分割的字符串是否相同
Sep 19 Javascript
JavaScript使用replace函数替换字符串的方法
Apr 06 Javascript
ES6中Symbol类型用法实例详解
Apr 06 Javascript
Vue $emit $refs子父组件间方法的调用实例
Sep 12 Javascript
详解Vue CLI 3.0脚手架如何mock数据
Nov 23 Javascript
vue组件中iview的modal组件爬坑问题之modal的显示与否应该是使用v-show
Apr 12 Javascript
Angular 2使用路由自定义弹出组件toast操作示例
May 10 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
PHP设计模式 注册表模式(多个类的注册)
2012/02/05 PHP
Yii2选项卡的简单使用
2017/05/26 PHP
JS 中document.URL 和 windows.location.href 的区别
2009/11/11 Javascript
JQuery each()函数如何优化循环DOM结构的性能
2012/12/10 Javascript
JS刷新框架外页面七种实现代码
2013/02/18 Javascript
js中prototype用法详细介绍
2013/11/14 Javascript
悬浮数字的实现案例
2014/02/19 Javascript
JavaScript简单遍历DOM对象所有属性的实现方法
2015/10/21 Javascript
jQuery实现可关闭固定于底(顶)部的工具条菜单效果
2015/11/06 Javascript
Node.js的基本知识简单汇总
2016/09/19 Javascript
AngularJS入门教程之过滤器用法示例
2016/11/02 Javascript
详解js加减乘除精确计算
2019/03/19 Javascript
javascrpt密码强度校验函数详解
2020/03/18 Javascript
一篇文章带你使用Typescript封装一个Vue组件(简单易懂)
2020/06/05 Javascript
vue iview 隐藏Table组件里的某一列操作
2020/11/13 Javascript
vue-router定义元信息meta操作
2020/12/07 Vue.js
python中wx将图标显示在右下角的脚本代码
2013/03/08 Python
python清除字符串中间空格的实例讲解
2018/05/11 Python
Django框架视图层URL映射与反向解析实例分析
2019/07/29 Python
Python 自动登录淘宝并保存登录信息的方法
2019/09/04 Python
python Manager 之dict KeyError问题的解决
2019/12/21 Python
Python调用钉钉自定义机器人的实现
2020/01/03 Python
python 基于selectors库实现文件上传与下载
2020/12/31 Python
浅析HTML5页面元素及属性
2021/01/20 HTML / CSS
马来西亚在线药房:RoyalePharma
2019/12/01 全球购物
请写出 float x 与"零值"比较的 if 语句
2016/01/04 面试题
产品工艺师的岗位职责
2013/11/15 职场文书
建筑系毕业生自我鉴定
2014/01/24 职场文书
鼓舞士气的口号
2014/06/16 职场文书
高中学生自我评价范文
2014/09/23 职场文书
入党个人总结范文
2015/03/02 职场文书
前台岗位职责范本
2015/04/16 职场文书
2016年端午节校园广播稿
2015/12/18 职场文书
工伤调解协议书
2016/03/21 职场文书
GO语言异常处理分析 err接口及defer延迟
2022/04/14 Golang
java实现web实时消息推送的七种方案
2022/07/23 Java/Android