JavaScript--数据结构与算法之二叉树

树是一种非线性的数据结构,以分层的方式存储数据。
二叉树:查找非常快,而且二叉树添加或者删除元素也非常快。
形象的可以描述为组织结构图,用来描述一个组织的结构。树是由边连接的点组成。
树的一些基本概念:
根节点:一棵树最上面的节点。
父节点:一个节点下面连接多个节点,该节点是父节点。
子节点:父节点下面的节点。(一个节点可以有0,1,或者多个子节点)
叶子节点:没有任何子节点的节点。
路径:从一个节点到另一个节点的这一组边。
树的遍历:以某种特定顺序访问树中所有的节点。
树的分层:根节点是0层,它的子节点是第一层以此类推。
树的深度:书的层数就是深度。
键:每个节点都有一个与之相关的值。
二叉树和二叉查找树
二叉树:一种特殊的树,子节点不超过两个将子树节点的个数限定为2,可以写出高效的程序在树中插入、查找、删除数据。
左右节点:父节点的两个子节点。
二叉查找树:是一种特殊的二叉树,相对较小的节点存在左节点,较大的存在右节点。这一特性是的查找的效率很高。
1、实现二叉查找树:
又节点组成,定义的第一个对象是Node,和链表的Node对象相似。
Node对象既能保存保存数据,也能保存和其他节点链接(left,right),show()用来显示保存在节点中的数据。
        function Node(data,left,right) {this.data = data;this.left = left;this.right = right;//this.show = show;
        }Node.prototype.show = function() {return this.data;};

  二叉树的创建:binary search tree

二叉树的创建:binary search tree
该类只有一个数据成员,表示二叉树查找树根节点的Node对象,初始化null;
BST有一个insert()方法,用来插入新节点,有点复杂,首先创建一个Node对象,将对象传入该数据中。检查BST是否有根结点,如果没有则是新树,该节点是根节点。否则待插入节点不是根节点,需要遍历BST,找到插入的适当位置。该过程类似与遍历链表。用一个变量存储当前结点,一层层地遍历BST。进入BST以后,下一步就是决定将节点放在什么地方,找到正确的插入点。
1)设置根节点为当前节点。
2)如果待插入节点保存的数据小于当前节点,则设置新的当前节点为原节点的左节点;反之4)
3)如果当前节点的左节点为null,就将新的节点插入这个位置,退出循环;反之执行下一次循环。
4)设置新的当前节点为原节点的右节点。
5)如果当前节点的右节点为null,就将新的节点插入这个位置,推出循环;反之执行下一次循环;
 
        function BST() {this.root = null;//this.insert = insert;this.preOrder = preOrder;//先序遍历this.inOrder = inOrder;//中序遍历this.postOrder = postOrder;//后序遍历
}BST.prototype.insert = function(data) {var _node = new Node(data,null,null);if(this.root == null) {this.root = _node;}else{var _current = this.root;var _parent;while(true) {_parent = _current;if(data < _current.data) {_current = _current.left;if(_current == null) {_parent.left = _node;break;}}else{_current = _current.right;if(_current == null) {_parent.right = _node;break;}}}}};
2、遍历二叉树
方式:先序,中序,后序。(都是以根为参照访问)
先序:先访问根节点,再以升序的方式访问左子树和右子树。
中序:以升序的方式访问左中右的次序。
后序:先访问叶子节点,从左子树到右子树再到根节点。
        //先序遍历preOrderfunction preOrder (node) {if(!(node == null)) {console.log(node.show());preOrder(node.left);preOrder(node.right);}}//test...var bst = new BST();bst.insert(23);bst.insert(45);bst.insert(16);bst.insert(37);bst.insert(3);bst.insert(99);bst.insert(22);preOrder(bst.root);//中序遍历inOrderfunction inOrder (node) {if(!(node == null)) {inOrder(node.left);console.log(node.show());inOrder(node.right);}}console.log("--------------------");inOrder(bst.root);//后序遍历inOrderfunction postOrder (node) {if(!(node == null)) {postOrder(node.left);postOrder(node.right);console.log(node.show());}}console.log("--------------------");postOrder(bst.root);
//完整代码:
        ~(function() {function Node(data,left,right) {this.data = data;this.left = left;this.right = right;//this.show = show;
            }Node.prototype.show = function() {return this.data;};function BST() {this.root = null;//this.insert = insert;this.preOrder = preOrder;//先序遍历this.inOrder = inOrder;//中序遍历this.postOrder = postOrder;//后序遍历
}BST.prototype.insert = function(data) {var _node = new Node(data,null,null);if(this.root == null) {this.root = _node;}else{var _current = this.root;var _parent;while(true) {_parent = _current;if(data < _current.data) {_current = _current.left;if(_current == null) {_parent.left = _node;break;}}else{_current = _current.right;if(_current == null) {_parent.right = _node;break;}}}}};//先序遍历preOrderfunction preOrder (node) {if(!(node == null)) {console.log(node.show());preOrder(node.left);preOrder(node.right);}}//中序遍历inOrderfunction inOrder (node) {if(!(node == null)) {inOrder(node.left);console.log(node.show());inOrder(node.right);}}//后序遍历inOrderfunction postOrder (node) {if(!(node == null)) {postOrder(node.left);postOrder(node.right);console.log(node.show());}}})();

 3、二叉树上的查找:

1)查找最小值;
2)查找最大值;
3)查找给定值。
最大最小值的查找比较简单,只要遍历到最左,最右即可。
        BST.prototype.getMin = function() {var _current = this.root;while(!(_current.left == null)) {_current = _current.left;}return _current.data;};BST.prototype.getMax = function () {var _current = this.root;while(!(_current.right == null)) {_current = _current.right;}return _current.data;};console.log("-----------");console.log( bst.getMin() );console.log( bst.getMax() );
查找给定值:find(); 需要比较该值和当前节点上的值的大小。通过比较大小,确定左遍历还是右遍历。
        BST.prototype.find = function(data) {var _current = this.root;while(_current != null) {if(_current.data == data) {return _current;}else if(data < _current.data) {_current = _current.left;}else{_current = _current.right;}}return null;//没找到返回null
        };console.log("-----------");console.log( bst.find(99) );

 4、删除二叉查找树上的节点

删除操作相对复杂,分为三种情况
1)删除叶子节点(没有子节点的节点)
2)删除只有一个子节点
3)删除包含两个子节点
删除时要删除数据和删除节点。
算法具体过程:
先判断当前节点是否包含待删除的数据,如果包含则删除该节点。如果不包含则比较当前节点上的数据和待删除的数据(删除根节点)。如果不包含,则比较当前节点的数据和待删除的数据。如果待删除数据小于当前节点上的数据,则移至当前结点的左子树节点继续比较;如果大于当前节点上的数据,则移至当前节点的右子节点继续比较。
叶子节:只需要将从父节点指向它的链接指向null;
删除节点只包含一个子节点:原本只想他的节点就的做些调整,使其指向它的子节点。
删除包含两个子节点:一种是查找待删除节点左子树上的最大值,要么查找其右子树上的最小值。
这个过程有两个方法完成,一个删除数据remove();,一个删除节点removeNode();
        function remove(data) {root = removeNode(this.root,data);}function getSmallest(node) {if (node.left == null) {return node;}else {return getSmallest(node.left);}}function removeNode(node,data) {if(node == null) {return null;}if(data == node.data) {if(node.left == null && node.right == null) {//叶子节点return null;}if(node.left == null) {//没有左子树return node.right;}if(node.right == null) {//没有右子树return node.left;}//有两个子节点的节点var _tempNode = getSmallest(node.right);//采用右子树上的最小值node.data = _tempNode.data;node.right = removeNode(node.right,_tempNode.data);return node;}else if(data < node.data) {node.left = removeNode(node.left,data);return node;}else {node.right = removeNode(node.right,data);return node;}}//bst.remove(3);
        preOrder(bst.root);//console.log( bst.show() );

 

转载于:https://www.cnblogs.com/intelwisd/p/7755534.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/399495.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

PHP 函数调用跟踪

//PHP 函数调用跟踪 $backtrace the_custom_logo(); array_shift($backtrace); var_dump($backtrace);

SpringSecurity6 | 失败后的跳转

✅作者简介:大家好,我是Leo,热爱Java后端开发者,一个想要与大家共同进步的男人😉😉 🍎个人主页:Leo的博客 💞当前专栏: Java从入门到精通 ✨特色专栏: MySQL学习 🥭本文内容: SpringSecurity6 | 失败后的跳转 📚个人知识库: Leo知识库,欢迎大家访问 学习…

与其他.Net异步模式和类型进行互操作

返回该系列目录《基于Task的异步模式--全面介绍》 Tasks和异步编程模型APM(Tasks and the Asynchronous Programming Model) 从APM到Tasks APM模式依赖两个对应的方法来表示一个异步操作&#xff1a;BeginMethodName和EndMethodName。在高级别&#xff0c;begin方法接受的参数和…

[Android]AndroidBucket增加碎片SubLayout功能及AISubLayout的注解支持

以下内容为原创&#xff0c;转载请注明&#xff1a; 来自天天博客&#xff1a;http://www.cnblogs.com/tiantianbyconan/p/3709957.html 之前写过一篇博客&#xff0c;是使用Fragment来实现TabHost的效果&#xff0c;并且模拟TabHost的切换各个fragment生命周期的调用&#xff…

更新说明

按暂时的设想&#xff0c;这个 blog 近期主要会更新三个方面的内容。 其一&#xff0c;是关于 Andrew Ng 在 coursa 上开设的 Machine Learning 的课程。 我不打算放课堂的笔记或者实录&#xff0c;而是主要分析一些作业的小项目的实现思路以及一些补充性的内容。有机会的话也试…

Java设计模式6:策略模式

策略模式 策略模式的用意是针对一组算法&#xff0c;将每一个算法封装到具有共同接口的独立类中&#xff0c;从而使得它们可以相互替换。策略模式使得算法可以在不影响到客户端的情况下发生变化。 策略模式的结构 策略模式是对算法的包装&#xff0c;是把使用算法的责任和算法本…

WordPress 获取当前页面 ID 的几大方法

https://zhangzifan.com/wordpress-get-id.html 在很多的 WordPress 主题或者插件功能的开发中&#xff0c;我们总是需要获取到 WordPress 给每个页面定义的 ID&#xff0c;不然也某些情况下是无法确定这是哪一个页面&#xff0c;针对于文章或者页面的 ID 获取基本可以使用 get…

王者荣耀交流协会第四次Scrum立会

拍照的是王磊同学&#xff0c;没有出镜。 开会时间&#xff1a;2017年10月30日下午18&#xff1a;45-19&#xff1a;16 共计31分钟 开会地点&#xff1a;一食堂二楼靠近窗户倒数第四排 今日完成工作进度&#xff1a; 袁玥同学完成了点击按钮刷新时间的功能代码&#xff1b; 王…

Python在信号与系统(1)——Hilbert兑换,Hilbert在国家统计局的包络检测应用,FIR_LPF滤波器设计,格鲁吉亚也迫使高FM(PM)调制...

谢谢董老师&#xff0c;董老师是个好老师。 心情久久不能平静&#xff0c;主要是高频这门课的分析方法实在是让我难以理解&#xff0c;公式也背只是&#xff0c;还是放放吧。 近期厌恶了Matlab臃肿的体积和频繁的读写对我的Mac的损害&#xff0c;所以学习了一下Python这一轻量级…

如何在WP-Config中设置WordPress错误日志

https://baijiahao.baidu.com/s?id1622279671500148245&wfrspider&forpc 你想在wp-config文件中设置WordPress错误日志吗&#xff1f;WordPress中的wp-config文件不仅控制您的WordPress网站设置&#xff0c;它也是一个非常有用的调试工具&#xff0c;可帮助您查找和修…

[再寄小读者之数学篇](2014-04-22 平方差公式在矩阵中的表达)

设 $A,B$ 都是 $n$ 阶复方阵, 且 $A^2B^22AB$. 证明: (1) $AB-BA$ 不可逆; (2) 如果 $\rank(A-B)1$, 那么 $ABBA$. 转载于:https://www.cnblogs.com/zhangzujin/p/3712973.html

C#:ref和out的联系及区别。

总结以上四条得到ref和out使用时的区别是&#xff1a;①&#xff1a;ref指定的参数在函数调用时候必须初始化&#xff0c;不能为空的引用。而out指定的参数在函数调用时候可以不初始化&#xff1b;②&#xff1a;out指定的参数在进入函数时会清空自己&#xff0c;必须在函数内部…

wordpress启用侧边栏小工具

http://www.seo628.com/1872.html wordpress后台默认不显示小工具选项&#xff0c;开发者需要启用小工具功能并把小工具在相应的前台位置调用出来&#xff0c;这样才能在后台直接拖动生成侧边栏。 激活小工具 激活小工具需要在functions.php中注册至少一个侧边栏 register_s…

comparator接口与Comparable接口的区别

Comparable & Comparator 都是用来实现集合中元素的比较、排序的&#xff0c;只是 Comparable 是在集合内部定义的方法实现的排序&#xff0c;Comparator 是在集合外部实现的排序&#xff0c;所以&#xff0c;如想实现排序&#xff0c;就需要在集合外定义 Comparator 接口的…

详解 Spotlight on MySQL监控MySQL服务器

前一章详解了Spotlight on Unix 监控Linux服务器 &#xff0c;今天再来看看Spotlight on MySQL怎么监控MySQL服务器。 注&#xff1a;http://www.cnblogs.com/Javame/p/3685512.html 第一步: 下载并安装mysql-connector-3.5x Spotlight on MySQL 连接mysql必须使用mysql-connec…

lua------------------Unity3D研究院编辑器之打开unity不可识别的文件(十三)

Unity3D研究院编辑器之打开unity不可识别的文件&#xff08;十三&#xff09; 雨松MOMO 【Unity3D拓展编辑器】 围观8597次 9 条评论 编辑日期&#xff1a;2017-03-02 字体&#xff1a;大 中 小 有些特殊后缀名的文件在unity里是不可识别的。如下图所示&#xff0c;这里我把文本…

一起Polyfill系列:Function.prototype.bind的四个阶段

昨天边参考es5-shim边自己实现Function.prototype.bind&#xff0c;发现有不少以前忽视了的地方&#xff0c;这里就作为一个小总结吧。 一、Function.prototype.bind的作用 其实它就是用来静态绑定函数执行上下文的this属性&#xff0c;并且不随函数的调用方式而变化。 示例&am…

Window 通过cmd查看端口占用、相应进程、杀死进程等的命令【转】

一、 查看所有进程占用的端口 在开始-运行-cmd,输入&#xff1a;netstat –ano可以查看所有进程 二、查看占用指定端口的程序 当你在用tomcat发布程序时&#xff0c;经常会遇到端口被占用的情况&#xff0c;我们想知道是哪个程序或进程占用了端口&#xff0c;可以用该命令 ne…

盘点18个免费的WordPress主题后台选项开发框架

https://yusi123.com/3205.html/3 13.Warp Framework Warp框架不仅支持WordPress和Joomla,还可以可扩展到其他的适用Web程序。使用Warp框架你可以轻松的定制你需要的功能。 该框架是来自Yootheme团队。看看他们出的主题&#xff0c;你就知道这个绝对是精品了。精心设计的界面和…

lua----------------使用VS2015搭建lua开发环境的一些侥幸成功经验,

所以本篇博文介绍在Windows平台下&#xff0c;使用VS2015搭建lua开发环境的一些侥幸成功经验&#xff0c;安装过程参考网上教程&#xff0c;安装过程如下&#xff08;参考http://www.byjth.com/lua/33.html&#xff09; 一 生成lua5.3.lib 1、下载并编译lua源码 首先进入lua官…