package com.core.algorithm.tree;
/**
* 二叉查找树节点 左子树比根节点小,右子树比根节点大
* Created by yuanqingjing on 2020/3/4
*/
public class BinarySearchNode<T extends Comparable<? super T>> {
private static class BinaryNode<T> {
public BinaryNode(T data) {
this.data = data;
this.left = null;
this.right = null;
}
public BinaryNode(T data, BinaryNode<T> left, BinaryNode<T> right) {
this.data = data;
this.left = left;
this.right = right;
}
private T data;
private BinaryNode<T> left; //左孩子
private BinaryNode<T> right; //右孩子
}
private BinaryNode<T> root;
public BinarySearchNode() {
this.root = null;
}
/**
* 新增二叉查找树节点,拿元素和根节点元素比较,如果比他小,则放在节点的左子树,
* 如果比他大,则放在右子树,直到有一个节点左子树或右子树为null,就放在这个节点
* 的左孩子节点或右孩子节点
*
* @param element
* @param root
* @return
*/
public BinaryNode<T> insert(T element, BinaryNode<T> root) {
if (root == null) {
return new BinaryNode<T>(element, null, null);
}
int compareResult = element.compareTo(root.data);
if (compareResult < 0) {
root.left = insert(element, root.left);
} else if (compareResult > 0) {
root.right = insert(element, root.right);
}
return root;
}
/**
* 删除这个元素对应的节点
* 首先找到这个元素对应的节点,删除分两种情况
* 1.如果这个节点只有一个子节点,那么删除的时候直接让这个节点
* 等于子节点就可以满足二叉查找树的性质
* 2.如果这个节点有两个子节点,即既有左子树又有右子树,首先找到右子树的最小节点,让
* 这个节点的值为右子树最小节点的值,然后删除右子树最小节点
* @param element
* @param root
* @return
*/
public BinaryNode<T> remove(T element, BinaryNode<T> root) {
if (root == null)
return root;
int compareResult = element.compareTo(root.data);
if (compareResult < 0) {
root.left = remove(element, root.left);
} else if (compareResult > 0) {
root.right = remove(element, root.right);
} else if (root.left != null && root.right != null) {
root.data = findMin(root.right).data;
root.right = remove(root.data, root.right);
} else {
root = (root.left == null ? root.right : root.left);
}
return root;
}
public void makeEmpty() {
this.root = null;
}
public boolean isEmpty() {
return root == null;
}
public boolean contains(T x) {
return contains(x, root);
}
/**
* 查找二叉查找树中最小值
*
* @return
*/
public T findMin() {
if (isEmpty())
return null;
return findMin(root).data;
}
/**
* 查找二叉查找树中最大值
*
* @return
*/
public T findMax() {
if (isEmpty())
return null;
return findMax(root).data;
}
/**
* 一直找根节点的左子树,直至这个节点没有左子树就是最小节点
*
* @param root
* @return
*/
public BinaryNode<T> findMin(BinaryNode<T> root) {
if (root == null || root.left == null)
return root;
return findMin(root.left);
}
/**
* 一直找根节点的右子树,直到节点没有右子树,这个节点就是最大的
*
* @param root
* @return
*/
public BinaryNode<T> findMax(BinaryNode<T> root) {
if (root == null || root.right == null)
return root;
return findMax(root.right);
}
public boolean contains(T x, BinaryNode<T> root) {
if (x == null)
return false;
int compareResult = x.compareTo(root.data);
if (compareResult < 0) {
return contains(x, root.left);
} else if (compareResult > 0) {
return contains(x, root.right);
}
return true;//match 匹配
}
/**
* 先序遍历 DLR 根节点->左子树->右子树
*
* @param root
*/
public void preOrderTraversal(BinaryNode<T> root) {
if (root == null)
return;
System.out.println(root.data);
preOrderTraversal(root.left);
preOrderTraversal(root.right);
}
/**
* 中序遍历 LDR 左子树->根节点->右子树
*
* @param root
*/
public void inOrderTraversal(BinaryNode<T> root) {
if (root == null)
return;
inOrderTraversal(root.left);
System.out.println(root.data);
inOrderTraversal(root.right);
}
/**
* 后序遍历 LRD 左子树->右子树->根节点
*
* @param root
*/
public void postOrderTraversal(BinaryNode<T> root) {
if (root == null) {
return;
}
postOrderTraversal(root.left);
postOrderTraversal(root.right);
System.out.println(root.data);
}
public static void main(String[] args) {
BinarySearchNode<Integer> bst = new BinarySearchNode<>();
BinaryNode root = bst.insert(6, null);
root = bst.insert(2, root);
root = bst.insert(1, root);
root = bst.insert(5, root);
root = bst.insert(3, root);
root = bst.insert(4, root);
root = bst.insert(8, root);
System.out.println(" 先序遍历");
bst.preOrderTraversal(root);
System.out.println(" 中序遍历");
bst.inOrderTraversal(root);
System.out.println(" 后序遍历");
bst.postOrderTraversal(root);
bst.remove(2, root);
System.out.println(" 先序遍历");
bst.preOrderTraversal(root);
}
}