package com.learn.tree;
/**
* 二叉查找树
* 满二叉树:除了叶子节点外,每个节点都有两个子节点
* 完全二叉树:叶子节点都在最底下两层,最后一层得叶子节点都靠左排列。并且除了最后一层,其他层得节点个数都要达到最大
* 时间复杂度O(n)
* @author liuyuzhen
*/
public class BinarySearchTree {
private TreeNode root;
private TreeNode getRoot() {
return root;
}
/**
* 前序遍历
* 递归公式: 先打印自己 在打印左节点和右节点
*/
public void preOrder(TreeNode treeNode) {
System.out.println(treeNode.getContent());
if (treeNode.getLeftNode() != null) {
preOrder(treeNode.getLeftNode());
}
if (treeNode.getRightNode() != null) {
preOrder(treeNode.getRightNode());
}
}
/**
* 中序遍历
* 递归公式:先打印它得左子树,然后再打印它本身,最后打印他得右子树
*/
public void innerOrder(TreeNode treeNode) {
if (treeNode.getLeftNode() != null) {
innerOrder(treeNode.getLeftNode());
}
System.out.println(treeNode.getContent());
if (treeNode.getRightNode() != null) {
innerOrder(treeNode.getRightNode());
}
}
/**
* 后序遍历
* 递归公式:先打印左子树,然后打印他的右子树,最后打印本身
*/
private void postOrder(TreeNode treeNode) {
if (treeNode.getLeftNode() != null) {
postOrder(treeNode.getLeftNode());
}
if (treeNode.getRightNode() != null) {
postOrder(treeNode.getRightNode());
}
System.out.println(treeNode.getContent());
}
/**
* 查找
*
* @param data 查找的数据
*/
public TreeNode find(int data) {
TreeNode p = root;
while (p != null) {
if (data == p.getContent()) {
return p;
} else if (data < p.getContent()) {
p = p.getLeftNode();
} else {
p = p.getRightNode();
}
}
return null;
}
/**
* 插入
*/
public void insert(int data) {
buildTree(root, data);
}
/**
* 删除
* 1.如果要删除的节点没有子节点,我们只需要直接将父节点中,指向删除节点的指针设置为NULL
* 2.如果删除的节点只有一个子节点(只有左节点或者只有右节点),我们只需要更新父节点,指向删除节点的指针,让它指向要删除的子节点
* 3.如果要删除的节点有两个子节点,我们需要找到这个个节点的右子树中的最小节点,把它替换到要删除的节点上。然后再删除这个最小节点,因为最小节点肯定没有左子节点
*/
public void del(int data) {
TreeNode p = root;//p指向被删除的节点,初始化指向根节点
TreeNode pp = null;//pp指向p的夫节点
while (p != null && p.getContent() != data) {
pp = p;
if (data > p.getContent()) {
p = p.getRightNode();
} else {
p = p.getLeftNode();
}
}
//没有找到
if (p == null) {
return;
}
// 要删除的节点有两个子节点
if (p.getRightNode() != null && p.getLeftNode() != null) {
TreeNode minP = p.getRightNode();
TreeNode minPP = p;
// 找到该节点的右节点下的最小左节点
while (minP.getLeftNode() != null) {
minPP = minP;
minP = minP.getLeftNode();
}
// 将该节点数据替换到P中
p.setContent(minP.getContent());
// 下面就变成了删除minP
p = minP;
pp = minPP;
}
// 删除节点是叶子节点或者只有一个子节点
TreeNode child;
if (p.getLeftNode() != null) {
child = p.getLeftNode();
} else if (p.getRightNode() != null) {
child = p.getRightNode();
} else {
child = null;
}
// 删除的是根节点
if (pp == null) {
root = child;
} else if (pp.getLeftNode() == p) {
pp.setLeftNode(child);
} else {
pp.setRightNode(child);
}
}
/**
* 快速查找最大节点
*/
public int findMin() {
TreeNode p = root;
while (p.getLeftNode() != null) {
p = p.getLeftNode();
}
return p.getContent();
}
/**
* 快速查找最小节点
*/
public int findMax() {
TreeNode p = root;
while (p.getRightNode() != null) {
p = p.getRightNode();
}
return p.getContent();
}
public void buildTree(TreeNode treeNode, int data) {
// 根节点没有,创建根节点
if (root == null) {
root = new TreeNode(data);
} else {
if (data < treeNode.getContent()) {
if (treeNode.getLeftNode() == null) {
treeNode.setLeftNode(new TreeNode(data));
} else {
buildTree(treeNode.getLeftNode(), data);
}
} else {
if (treeNode.getRightNode() == null) {
treeNode.setRightNode(new TreeNode(data));
} else {
buildTree(treeNode.getRightNode(), data);
}
}
}
}
public static BinarySearchTree createBinaryTree(int[] dataArr) {
BinarySearchTree binaryTree = new BinarySearchTree();
for (int data : dataArr) {
binaryTree.buildTree(binaryTree.getRoot(), data);
}
return binaryTree;
}
/**
* 72
* 37 80
* 29 55
* 51
*/
public static void main(String[] args) {
int[] dataArr = {72, 37, 29, 55, 51, 80};
BinarySearchTree binaryTree = createBinaryTree(dataArr);
System.out.println("---------------前序遍历--------------------");
// 前序遍历
binaryTree.preOrder(binaryTree.getRoot());
System.out.println("---------------中序遍历--------------------");
// 中序遍历
binaryTree.innerOrder(binaryTree.getRoot());
System.out.println("---------------后序遍历--------------------");
// 后序遍历
binaryTree.postOrder(binaryTree.getRoot());
System.out.println("---------------查找--------------------");
// 查找
TreeNode treeNode = binaryTree.find(80);
System.out.println(treeNode);
System.out.println("---------------插入--------------------");
// 插入
binaryTree.insert(81);
binaryTree.preOrder(binaryTree.getRoot());
// 删除
System.out.println("---------------删除--------------------");
binaryTree.del(72);
binaryTree.preOrder(binaryTree.getRoot());
// 查找最大
System.out.println("---------------查找最大\\最小节点--------------------");
System.out.println(binaryTree.findMax() + " " + binaryTree.findMin());
}
}
/**
* 子节点
*/
class TreeNode {
// 左节点
private TreeNode leftNode;
// 右节点
private TreeNode rightNode;
// 存储内容
private int content;
public TreeNode getLeftNode() {
return leftNode;
}
public void setLeftNode(TreeNode leftNode) {
this.leftNode = leftNode;
}
public TreeNode getRightNode() {
return rightNode;
}
public void setRightNode(TreeNode rightNode) {
this.rightNode = rightNode;
}
public int getContent() {
return content;
}
public void setContent(int content) {
this.content = content;
}
public TreeNode(int content) {
this.content = content;
}
}