二叉排序树
二叉排序树: BST,对于二叉树的任何一个非叶子结点,要求左子节点的值比当前节点的值小,右结点的值比当前结点的值大(临界情况,我们可以放在左右都行,但是要尽量避免相同值)
例如
如果我们要在插入一个结点 {2}
这个就是二叉排序树的数据结构
二叉排序树的创建和遍历(前中后)
我们就以上图的数组作为结点进行二叉树创建,我们在创建的过程中要考虑值相同的情况,在这我把他存放在了右子节点.即node.value<=node.right.value
先来看一下这个树的功能方法structures图
Node 类属性
int value;//结点存放值
Node left;//左结点信息
Node right;//右结点信息
public void add(Node node) {//添加结点功能
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);
}
}
//中序表达式
public void infixOrder() {
if (this.left != null) {
this.left.infixOrder();
}
System.out.println(this);
if (this.right != null) {
this.right.infixOrder();
}
BST类
Node root=null;
public void addNode(Node node) {
if (root == null) {
root = node;
return;
} else {
root.add(node);
}
}
//中序表达式
public void infixOrder() {
if (root != null) {
root.infixOrder();
} else {
System.out.println("binary tree is none");
}
}
二叉排序树删除结点(逻辑性比较强)
我们以下面这张图为例来分析删除条件
上图基本包括了所有判断条件
1)要删除结点{1},{9},{6},{15}为叶子结点
2)要删除结点{3},{12}为只有一颗树的结点
3)要删除结点{其他都是}为有两颗树及以上的结点
分析
第一种情况:
通过遍历找到当前要删除结点,直接删除,因为它已经没有子节点了
第二种情况:
我要删除{3},它有子节点
1)我们定义一个父节点临时结点,用于存储父节点的左右指针的信息改动值
所以我们要为它提供方法 Node searchParent(int value);
2)我们还应该找到当前数据的结点位置,用于存储当前结点值信息
所以我们要为它提供方法 Node searchTarget(int value) ;
3)我们判断target结点是parent的子节点是左子结点,还是右子节点.
if parent.left!=null && parent.left.value==value
那么 再去判断target的节点是左结点还是右结点
if target.left==null&&target.rigth!=null
那么 我们交换 parent.left=target.rigth
一共判断四次,其他的我就不写了,逻辑就是这个样子
第三种情况
我们首先要从它的子树中找到一个最小的节点,进行提上来
所以我们定义方法:
public int findMinNode(Node node) {
Node target = node;
while (target.left != null) {
target = target.left;
}
delete(target.value);
return target.value;
}
然后我们再去判断条件
if 左右节点都不为空,那么我们怎么做
if 左结点不为空,右节点为空,我们怎么做
if左节点为空,右结点不为空,我们怎么做
逻辑代码我不分析了,因为比较简单
我们需要注意一个点,就是parent 为空的时候,就是当前节点未父节点,我们直接把root置为空
下面直接上代码,所有问题都写在一个总类里面了
package com.BinarySortTree;
import java.time.temporal.ValueRange;
/**
* created by wyl.. on 2019-08-29 下午 05:11
*/
public class BinarySortTree {
static class Node {
int value;
Node left;
Node right;
public Node(int value) {
this.value = value;
}
@Override
public String toString() {
return "Node:" + value +
',';
}
public void find(Node node,int value){
if (node.value==value){
System.out.println(value);
}
if (node.left!=null){
node=node.left;
node.find(node,value);
}else if (node.right!=null){
node=node.right;
node.find(node,value);
}else {
System.out.println("没有该值"); ;
}
}
public void add(Node node) {
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);
}
}
}
//中序表达式
public void infixOrder() {
if (this.left != null) {
this.left.infixOrder();
}
System.out.println(this);
if (this.right != null) {
this.right.infixOrder();
}
}
/**
* @param value 要查找值
* @return 返回值所在结点位置
*/
public Node searchTarget(int value) {
if (value == this.value) {
return this;
} else if (value < this.value) {
if (this.left == null) {
return null;
}
return this.left.searchTarget(value);
} else {
if (this.right == null) {
return null;
}
return this.right.searchTarget(value);
}
}
/**
* @param value 当前节点
* @return 父节点
*/
private Node searchParent(int value) {
if ((this.left != null && this.left.value == value)
|| (this.right != null && this.right.value == value)) {
return this;
} else {
if (value < this.value && this.left != null) {
return this.left.searchParent(value);
} else if (value >=/*=的值我们放在了右结点*/ this.value && this.right != null) {
return this.right.searchParent(value);
} else {
// System.out.println("没有找到父节点");
return null;
}
}
}
}
static class BST {
private Node root = null;
public BST() {
}
public void find(int value){
if (root==null){
try {
System.out.println("空树");
} catch (Exception e) {
e.printStackTrace();
}
}
if (root.value == value) {
System.out.println(value);
}else {
root.find(root, value);
}
}
public void addNode(Node node) {
if (root == null) {
root = node;
return;
} else {
root.add(node);
}
}
public void infixOrder() {
if (root != null) {
root.infixOrder();
} else {
System.out.println("binary tree is none");
}
}
/**
* 找到最小结点的值
*
* @param node
* @return
*/
public int findMinNode(Node node) {
Node target = node;
while (target.left != null) {
target = target.left;
}
delete(target.value);
return target.value;
}
public Node searchTarget(int value) {
if (root == null) {
return null;
} else {
return root.searchTarget(value);
}
}
public Node seartchParent(int value) {
if (root == null) {
return null;
} else {
return root.searchParent(value);
}
}
public void delete(int value) {
if (root == null) {
return;
} else {
Node target = root.searchTarget(value);
Node parent = root.searchParent(value);
if (target == null) {
return;
}
//如果我们发现二叉排序树,只有一个结点, 即 root.left==root.right==null
//如果我们发现二叉排序树,如果删除的是root结点,parent==null
if (parent == null) { //结点是root
root = null;
return;
} else if (target.left != null && target.right != null) {
int cur = findMinNode(target.right);
target.value = cur;
} else if (target.left == null && target.right != null) {
int rightMax=findMinNode(target.right);
target.value=rightMax;
} else if (target.left != null && target.right == null) {
int leftMax = findMinNode(target.left);
target.value=leftMax;
} else {
if (parent.left != null && parent.left.value == value) {
parent.left = null;
} else if (parent.right != null && parent.right.value == value) {
parent.right = null;
}
}
}
}
}
public static void main(String[] args) {
int[] arr = {7, 3, 10, 12, 5, 1, 9, 2};
BST bst = new BST();
for (int i = 0; i < arr.length; i++) {
bst.addNode(new Node(arr[i]));
}
bst.infixOrder();
bst.find(4);
bst.delete(1);
bst.infixOrder();
}
}
二叉树的学习,其实并不难,理清其中逻辑关系,代码很容易写出来。对于二叉树,链表这个都大量运用了递归思想。