js实现数据结构及算法之二叉树(Binary Tree)
树(Tree)
树是一种非线性的数据结构,分层存储
树常被用来存储具有层级关系的数据,也会被用来存储有序列表等
树和集合一样,不允许相同的元素存在
树由一组以边连接的节点组成
一棵树最上面的节点称为根节点,如果一个节点下面连接多个节点,那么该节点称为父节点,它下面的节点被称为子节点。一个节点可以有0个、1个或多个子节点。没有任何子节点的节点称为叶子节点
二叉树(Binary Tree)
二叉树是一种特殊的树,子节点个数不超过两个,且分别称为该结点的左子树(left subtree)与右子树(right subtree)
二叉查找树(BST)
二叉查找树是一种特殊的二叉树,相对较小的值保存在左节点,较大的值保存在右节点,这一特性使得查找效率很高
完全二叉树
若设二叉树的高度为h,除第 h 层外,其它各层 (1~h-1) 的结点数都达到最大个数,第h层有叶子结点,并且叶子结点都是从左到右依次排布,这就是完全二叉树
满二叉树
除了叶结点外每一个结点都有左右子叶且叶子结点都处在最底层的二叉树
平衡二叉树(AVL树)
它是一棵二叉排序树,且具有以下性质:它是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树
二叉树遍历
按一定的规则和顺序走遍二叉树的所有结点,使每一个结点都被访问一次,而且只被访问一次,这个操作被称为树的遍历,是对树的一种最基本的运算。
按照根节点访问的顺序不同,树的遍历分为以下三种:前序遍历,中序遍历,后序遍历;
前序遍历:根节点->左子树->右子树
23->16->22->45->37->99
中序遍历:左子树->根节点->右子树
16->22->23->37->45->99
后序遍历:左子树->右子树->根节点
22->16->37->99->45->23
决定是先中后遍历的根节点的遍历位置,若根节点是第一个遍历,便是先序遍历;若根节点是第二个遍历,便是中序遍历;若根节点是最后一个遍历,便是后序遍历
js二叉查找树(BST)
实现二叉树的难点,是插入与删除,需要注意,如果使用中序遍历,便是排序了
/*** 一个简单的二叉查找树(BST)* @constructor*///节点定义function Node(data, left, right) {this.data = data; // 数据this.left = left; // 左节点this.right = right; // 右节点this.show = show; // 显示节点数据}//二叉树类function BST() {this.root = null; // 根节点this.insert = insert; // 插入节点this.preOrder = preOrder; // 先序遍历this.inOrder = inOrder; // 中序遍历this.postOrder = postOrder; // 后序遍历this.find = find; // 查找节点this.getMin = getMin; // 查找最小值this.getMax = getMax; // 查找最大值this.remove = remove; // 删除节点this.removeNode = removeNode; // 删除节点}//显示节点数据function show() {return this.data}//插入节点/*首先要添加新的节点,首先需要创建一个Node对象,将数据传入该对象。其次要检查当前的BST树是否有根节点,如果没有,那么表示是一棵新数,该节点就为该树的根节点,那么插入这个过程就结束了;否则,就要继续进行下一步了。如果待插入节点不是根节点,那么就必须对BST进行遍历,找到合适的位置。该过程类似遍历链表,用一个变量存储当前节点,一层一层遍历BST,算法如下:1.设值当前节点为根节点2.如果待插入节点保存的数据小于当前节点,则新节点为原节点的左节点,反之,执行第4步3.如果当前节点的左节点为null,就将新节点放到这个位置,退出循环;反之,继续执行下一次循环4.设置新节点为原节点的右节点5.如果当前节点的右节点为null,就将新节点放到这个位置,退出循环;反之,继续执行下一次循环
*/function insert(data) {var n = new Node(data, null, null)if (this.root === null) {this.root = n} else {var current = this.rootvar parentwhile (true) {parent = currentif (data < current.data) {current = current.leftif (current === null) {parent.left = nbreak}} else {current = current.rightif (current === null) {parent.right = nbreak}}}}}//先序遍历function preOrder(node) {if (node !== null) {console.log(node.show())preOrder(node.left)preOrder(node.right)}}//中序遍历function inOrder(node) {if (node !== null) {inOrder(node.left)console.log(node.show())inOrder(node.right)}}//后序遍历function postOrder(node) {if (node !== null) {postOrder(node.left)postOrder(node.right)console.log(node.show())}}//查找节点function find(data) {var current = this.rootwhile (current !== null) {if (current.data === data) {return current} else if (data < current.data) {current = current.left} else {current = current.right}}return null}//查找最小值function getMin(root) {var current = this.root || rootwhile (current.left !== null) {current = current.left}return current}//查找最大值function getMax(root) {var current = this.root || rootwhile (current.right !== null) {current = current.right}return current}
/*
从BST中删除节点的操作最为复杂,其复杂程度取决于删除的节点位置。
如果待删除的节点没有子节点,那么非常简单。
如果删除包含左子节点或者右子节点,就变得稍微有些复杂。如果删除包含两个节点的节点最为复杂。
我们采用递归方法,来完成复杂的删除操作,我们定义 remove() 和 removeNode() 两个方法;
算法思想如下:
1.判断当前节点是否包含待删除的数据,如果包含,则删除该节点;
2.如果不包含,则比较当前节点上的数据和待删除树的的大小关系。
3.如果待删除的数据小于当前节点的数据,则移至当前节点的左子节点继续比较;
4.如果大于,则移至当前节点的右子节点继续比较。
5.如果待删除节点是叶子节点(没有子节点),那么只需要将从父节点指向它的链接指向变为null;
6.如果待删除节点含有一个子节点,那么原本指向它的节点需要做调整,使其指向它的子节点;
7.最后,如果待删除节点包含两个子节点,可以选择查找待删除节点左子树上的最大值或者查找其右子树上的最小值,
这里我们选择后一种。
因此,我们需要一个查找树上最小值的方法,后面会用它找到最小值创建一个临时节点,
将临时节点上的值复制到待删除节点,然后再删除临时节点;
*///删除操作function remove(data) {this.removeNode(this.root, data)}// 删除节点function removeNode(node, data) {if (node === null) return nullif (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 = getMin(node.right)node.data = tempNode.datanode.right = removeNode(node.right, tempNode.data)return node} else if (data > node.data) {node.right = removeNode(node.right, data)return node} else {node.left = removeNode(node.left, data)return node}}var bst = new BST()bst.insert(23);bst.insert(45);bst.insert(16);bst.insert(37);bst.insert(99);bst.insert(22);console.log('=====先序======')bst.preOrder(bst.root)console.log('=====中序======')bst.inOrder(bst.root)console.log('=====后序======')bst.postOrder(bst.root)console.log('=====remove======')bst.remove(23)console.log(bst)console.log('最小值->' + bst.getMin(bst.root))console.log('最大值->' + bst.getMax(bst.root))复制代码
js实现数据结构及算法之二叉树(Binary Tree)相关推荐
- 『数据结构与算法』解读树(Tree)和二叉树(Binary Tree)!
『数据结构与算法』解读树(Tree)和二叉树(Binary Tree)! 文章目录 一. 树 1.1. 树的定义 1.2. 树的基本术语 1.3. 树的性质 二. 二叉树 2.1. 二叉树的定义 2. ...
- 数据结构与算法练习-二叉树中序遍历
python数据结构与算法练习-二叉树中序遍历 二叉树中序遍历 思路 python实现 二叉树中序遍历 链接: link. 给定一个二叉树的根节点 root ,返回它的 中序 遍历. 样例 输入:ro ...
- 常考数据结构与算法:输出二叉树的右视图
题目描述 请根据二叉树的前序遍历,中序遍历恢复二叉树,并打印出二叉树的右视图 上图树的右视图为:{1,4,3,7} 做此题之前可以先做下面3道题: 1. 常考数据结构与算法:求二叉树的层序遍历 2.常 ...
- 数据结构与算法之二叉树的序列化和反序列化及判断一棵树是否为平衡二叉树
数据结构与算法之二叉树的序列化和反序列化及判断一棵树是否为平衡而二叉树 目录 二叉树的序列化和反序列化 判断一棵树是否为平衡而二叉树 1. 二叉树的序列化和反序列化 1. 递归版本序列化和反序列化 代 ...
- 数据结构与算法之二叉树的先序遍历,中序遍历,后序遍历
数据结构与算法之二叉树的先序遍历,中序遍历,后移遍历 目录 实现二叉树的先序,中序,后序遍历,包括递归方式和非递归方式 在二叉树中找到一个节点的后继节点 1. 实现二叉树的先序,中序,后序遍历,包括递 ...
- 数据结构与算法之-----二叉树(一)
[ 写在前面的话:本专栏的主要内容:数据结构与算法. 1.对于初识数据结构的小伙伴们,鉴于后面的数据结构的构建会使用到专栏前面的内容,包括具体数据结构的应用,所使用到的数据结构,也是自己构建的,未使用 ...
- 数据结构与算法 3:二叉树,遍历,创建,释放,拷贝,求高度,面试,线索树
[本文谢绝转载,原文来自http://990487026.blog.51cto.com] 树 数据结构与算法 3:二叉树,遍历,创建,释放,拷贝,求高度,面试,线索树二叉树的创建,关系建立二叉树的创建 ...
- 【数据结构】二叉树 (Binary Tree)
目录 一. 什么是树? 二. 二叉树 特殊二叉树 二叉树的性质 二叉树的存储 二叉树的遍历 二叉树的基本操作 一.什么是树? 之前咱们学习了一些简单的数据结构,如顺序表,链表,这些都是线性结构,线性结 ...
- 数据结构与算法:二叉树专题
数据结构与算法:二叉树专题 前言 前提条件 基础知识 二叉树链式存储结构 二叉树中序遍历 二叉树层序遍历 常见编程题 把一个有序整数数组放到二叉树中 逐层打印二叉树结点数据 求一棵二叉树的最大子树和 ...
最新文章
- c语言程序设计分段定时器,单片机C语言编程定时器的几种表达方式
- 转Java转iOS-第一个项目总结(2):遇到问题和解决方案
- 昕灵感应流行坊(Shop.25941.Cn)^_^全新开张
- B - Labyrinth Gym - 102798B
- leetcode41. First Missing Positive
- oracle 创建job
- 190707每日一句,一堂重要的人生之课Let it go, 穷则变变则通
- 初学者C语言输入输出挖坑填补处须知
- 邮件服务器匿名,smtp服务器发送匿名邮件
- 一阶惯性传感器的快速跟踪性能实现
- Python爬取某短视频热点
- 嵌入式系统多媒体框架分析
- 三十六以内某进制下的数转换为另一进制下的数(递归版,迭代版)——秦九昭算法
- Beaglebone Black——开机自动运行程序
- java chr()_chr码值对应列表大全
- Flink SQL语法检查
- Kafka or RabbitMQ:消息中间件选型深入分析
- 7.STM32F407ZG串口通信配置流程
- [FreeBSD] pf+altq实战[转]
- 怎样与团队成员沟通,从而提高团队的执行力?