package datastructure
/**
* 二叉树demo
*/
object BinaryTreeDemo {
def main(args: Array[String]): Unit = {
val root = new HeroNode(1, "宋江")
val hero2 = new HeroNode(2, "吴用")
val hero3 = new HeroNode(3, "卢俊义")
val hero4 = new HeroNode(4, "武松")
val hero5 = new HeroNode(5, "林冲")
root.left = hero2
root.right = hero3
hero3.left = hero5
hero3.right = hero4
val tree = new BinaryTree
tree.root = root
println("---------------前序遍历-------------------")
tree.perOrder()
println("---------------中序遍历-------------------")
tree.infixOrder()
println("---------------后序遍历-------------------")
tree.postOrder()
println("---------------前序查找-------------------")
val perOrderNode: HeroNode = tree.perOrderSearch(5)
if (perOrderNode != null) {
printf("找到了~ no = %d,name=%s\n", perOrderNode.no, perOrderNode.name)
} else {
println("没找到")
}
println("---------------中序查找-------------------")
val infixOrderNode: HeroNode = tree.infixOrderSearch(5)
if (infixOrderNode != null) {
printf("找到了~ no = %d,name=%s\n", infixOrderNode.no, infixOrderNode.name)
} else {
println("没找到")
}
println("---------------后序查找-------------------")
val postOrderNode: HeroNode = tree.postOrderSearch(5)
if (postOrderNode != null) {
printf("找到了~ no = %d,name=%s\n", postOrderNode.no, postOrderNode.name)
} else {
println("没找到")
}
println("---------------删除节点-------------------")
// tree.delNode(5)
// tree.delNode(3)
tree.delNode(1)
println("---------------前序遍历-------------------")
tree.perOrder()
}
}
class HeroNode(hNo: Int, hName: String) {
val no = hNo
var name = hName
var left: HeroNode = null
var right: HeroNode = null
def delNode(no: Int): Unit = {
if (this.left != null && this.left.no == no) {
this.left = null
return
}
if (this.right != null && this.right.no == no) {
this.right = null
return
}
if (this.left != null) {
this.left.delNode(no)
}
if (this.right != null) {
this.right.delNode(no)
}
}
//前序遍历
def preOrder(): Unit = {
printf("当前节点 no = %d,name = %s\n", no, name)
//递归调用
if (this.left != null) {
this.left.preOrder()
}
if (this.right != null) {
this.right.preOrder()
}
}
//前序查找
def preOrderSearch(no: Int): HeroNode = {
if (this.no == no) {
return this
}
var resNode: HeroNode = null
if (this.left != null) {
resNode = this.left.preOrderSearch(no)
}
if (resNode != null) {
return resNode
}
if (this.right != null) {
resNode = this.right.preOrderSearch(no)
}
resNode
}
//中序遍历
def infixOrder(): Unit = {
//递归调用
if (this.left != null) {
this.left.infixOrder()
}
printf("当前节点 no = %d,name = %s\n", no, name)
if (this.right != null) {
this.right.infixOrder()
}
}
def infixOrderSearch(no: Int): HeroNode = {
var resNode: HeroNode = null
if (this.left != null) {
resNode = this.left.infixOrderSearch(no)
}
if (resNode != null) {
return resNode
}
if (this.no == no) {
return this
}
if (this.right != null) {
resNode = this.right.infixOrderSearch(no)
}
resNode
}
def postOrder(): Unit = {
//递归调用
if (this.left != null) {
this.left.postOrder()
}
if (this.right != null) {
this.right.postOrder()
}
printf("当前节点 no = %d,name = %s\n", no, name)
}
def postOrderSearch(no: Int): HeroNode = {
var resNode: HeroNode = null
if (this.left != null) {
resNode = this.left.postOrderSearch(no)
}
if (resNode != null) {
return resNode
}
if (this.right != null) {
resNode = this.right.postOrderSearch(no)
}
if (resNode != null) {
return resNode
}
if (this.no == no) {
return this
}
resNode
}
}
class BinaryTree {
var root: HeroNode = null
def delNode(no: Int): Unit = {
if(root != null){
if(root.no == no){
root = null
}else{
root.delNode(no)
}
}
}
def perOrderSearch(no: Int): HeroNode = {
if (root != null) {
root.preOrderSearch(no)
} else {
null
}
}
def perOrder(): Unit = {
if (root != null) {
root.preOrder()
} else {
println("当前二叉树为空,不能遍历")
}
}
def infixOrderSearch(no: Int): HeroNode = {
if (root != null) {
root.infixOrderSearch(no)
} else {
null
}
}
def infixOrder(): Unit = {
if (root != null) {
root.infixOrder()
} else {
println("当前二叉树为空,不能遍历")
}
}
def postOrderSearch(no: Int): HeroNode = {
if (root != null) {
root.postOrderSearch(no)
} else {
null
}
}
def postOrder(): Unit = {
if (root != null) {
root.postOrder()
} else {
println("当前二叉树为空,不能遍历")
}
}
}
顺序二叉树
顺序存储二叉树的特点:
1) 顺序二叉树通常只考虑完全二叉树
2) 第 n 个元素的左子节点为 2 * n + 1
3) 第 n 个元素的右子节点为 2 * n + 2
4) 第 n 个元素的父节点为 (n-1) / 2
n : 表示二叉树中的第几个元素(按 0 开始编号如图所示)
需求: 给你一个数组 Array(1,2,3,4,5,6,7),要求以二叉树前序遍历的方式进行遍历。 前序遍历的结果应当为
1,2,4,5,3,6,7
代码实现:
package com.atguigu.chapter18.binarytree
object ArrayTreeDemo {
def main(args: Array[String]): Unit = {
val arr = Array(1,2,3,4,5,6,7)
val arrayTree = new ArrayTree(arr)
//前序遍历我们的数组
arrayTree.preOrder() //1,2,4,5,3,6,7
}
}
/*
课后练习:请同学们完
成对数组以二叉树中序,
后序遍历方式的代码.
*/
class ArrayTree(val arr:Array[Int]) {
//对 preOrder 进行一个重载
def preOrder(): Unit = {this.preOrder(0)
}
def preOrder(index:Int): Unit = {
if (arr == null || arr.length == 0) {
println("数组为空,不能按照二叉树前序遍历")
}
println(arr(index))
//向左递归遍历
if ((index * 2 + 1) < arr.length){
preOrder(index * 2 + 1)
}
//向右边递归遍历
if ((index * 2 + 2) < arr.length){
preOrder(index * 2 + 2)
}
}
}
二叉树排序树
给你一个数组 (7, 3, 10, 12, 5, 1, 9),要求能够高效的完成对数组的查询和添加
二叉排序树:BST: (Binary Sort(Search) Tree), 对于二叉排序树的任何一个非叶子节点,要求左子节点的值比当
前节点的值小,右子节点的值比当前节点的值大。
特别说明:如果有相同的值,可以将该节点放在左子节点或右子节点
比如针对前面的数组 (7, 3, 10, 12, 5, 1, 9) ,对应的二叉排序树为:
一个数组创建成对应的二叉排序树,并使用中序遍历二叉排序树,比如: 数组为 Array(7, 3, 10, 12, 5, 1, 9)
二叉排序树的删除
二叉排序树的删除情况比较复杂,有下面三种情况需要考虑
1) 删除叶子节点 (比如:2, 5, 9, 12)
2) 删除只有一颗子树的节点 (比如:1)
3) 删除有两颗子树的节点. (比如:7, 3,10 )
二叉排序树的代码实现
//Array(7, 3, 10, 12, 5, 1, 9) 做成一个二叉排序树
object BinarySortTreeDemo {
def main(args: Array[String]): Unit = {
//测试一把
val arr = Array(7, 3, 10, 12, 5, 1, 9, 2)
//创建一颗二叉排序树
val binarySortTree = new BinarySortTree
for (item <- arr) {
binarySortTree.add(new Node(item))
}
//遍历二叉排序树
binarySortTree.infixOrder() // 1,3,5,7,9,10,12
//删除
// binarySortTree.delNode(2)
// binarySortTree.delNode(5)
// binarySortTree.delNode(9)
// binarySortTree.delNode(12)
binarySortTree.delNode(10)
println("删除后~~~")
binarySortTree.infixOrder()
}
}
//定义节点
class Node(var value: Int) {
var left: Node = null
var right: Node = null
//查找某个节点,根据值
def search(value: Int): Node = {
//先判断当前节点是否是要删除的节点
if (value == this.value) {
return this
} else if (value < this.value) { //向左去找
if (this.left == null) {
return null
} else {
return this.left.search(value)
}
} else {
if (this.right == null) {
return null
} else { //递归向右子树查找
return this.right.search(value)
}
}
}
//找某个节点的父节点
def searchParent(value: Int): Node = {
//思路
//1. 先判断当前节点的左子节点或者右子节点是否是这个值
if ((this.left != null && this.left.value == value) ||
(this.right != null && this.right.value == value)) {
return this
} else {
if (this.left != null && value < this.value) { //说明需要向左边去递归查找
return this.left.searchParent(value)
} else if (this.right != null && value > this.value) { //说明需要向右边去递归查找
return this.right.searchParent(value)
} else {
null
}
}
}
//添加方法
def add(node: Node): Unit = {
if (node == null) { //如果节点为空,返回
return
}
//如果要插入的节点的值小于当前节点的值
if (node.value < this.value) {
if (this.left == null) {
//说明该节点下没有左子节点
this.left = node
} else {
//递归的进行插入
this.left.add(node)
}
} else { //如果要插入的节点的值不小于当前节点的值
if (this.right == null) {
this.right = node
} else {
//递归的进行插入
this.right.add(node)
}
}
}
//中序遍历
def infixOrder(): Unit = {
//向左递归输出左子树
if (this.left != null) {
this.left.infixOrder()
}
//先输出当前节点值
printf("节点信息 value=%d \n", value)
//向右边递归输出右子树
if (this.right != null) {
this.right.infixOrder()
}
}
}
//定义我们的二叉排序树
class BinarySortTree {
var root: Node = null
//删除某个右子树的最小值的节点,并返回最小值
def delRightTreeMin(node:Node): Int = {
var target = node
//使用 while 循环找到右子树的最小值
while (target.left != null){
target = target.left
}
val minValue = target.value
//删除最小值对应的节点
delNode(minValue)
return minValue
}
//查找节点
def search(value: Int): Node = {
if (root != null) {
return root.search(value)
} else {
return null
}
}
//查找父节点的方法
def searchParent(value: Int): Node = {
if (root != null) {
return root.searchParent(value)
} else {
return null
}
}
//删除节点
def delNode(value: Int): Unit = {
if (root == null) { //如果是空树,就不删除
return
}
//先看有没有要删除节点
var targetNode = search(value)
if (targetNode == null) { //没有要删除的节点,就直接返回
return
}
//查找 targetNode 的父节点
var parentNode = searchParent(value)
//1. 先考虑的是叶子节点
if (targetNode.left == null && targetNode.right == null) {
//判断删除的节点是 parentNode 的左子节点,还是右子节点
if (parentNode.left != null && parentNode.left.value == value) {
parentNode.left = null
} else {
parentNode.right = null
}
} else if (targetNode.left != null && targetNode.right != null) { // targetNode 只有两个子节点
val value = delRightTreeMin(targetNode.right)
targetNode.value = value
} else { //只有 targetNode 只有一个子节点
//判断 targetNode 是 parentNode 的左子节点还是右子节点
if (targetNode.left != null) { //要删除的节点的左子节点不为空
//判断 targetNode 是 parentNode 的左还是右
if (parentNode.left.value == value) {
parentNode.left = targetNode.left
} else {
parentNode.right = targetNode.left
}
} else {
//判断 targetNode 是 parentNode 的左还是右
if (parentNode.left.value == value) {
parentNode.left = targetNode.right
} else {
parentNode.right = targetNode.right
}
}
}
}
def add(node: Node): Unit = {
if (root == null) { //空树
root = node
} else {
root.add(node)
}
}
//中序遍历
def infixOrder(): Unit = {
if (root != null) {
root.infixOrder()
} else {
println("当前二叉树为空,不能遍历")
}
}
}