学习记录
package BinarySortTreeDemo;
public class BSTDemo {
public static void main(String[] args) {
// TODO Auto-generated method stub
BinarySortTree bst = new BinarySortTree();
int[] arr = { 7, 3, 10, 12, 5, 1, 9,2};
bst.initial(arr);
bst.traveral();
System.out.println(" after delete");
bst.delete(2);
bst.traveral();
}
}
//创建一个二叉排序树的结点类
class Node {
int data;
Node left;
Node right;
// 生成构造方法
public Node(int data) {
this.data = data;
}
// 重写toString
@Override
public String toString() {
return "Node [data=" + data + "]";
}
// 添加结点到二叉排序树中
public void add_node(Node node) {
// 判断加入的结点不为空
if (node == null) {
return;
}
// 对加入的结点数值与当前结点的值进行比较
if (this.data > node.data) {
if (this.left != null) {
this.left.add_node(node);
} else {
this.left = node;
}
} else if (this.data < node.data) {// 注意这里默认加入的结点值不相等
if (this.right != null) {
this.right.add_node(node);
} else {
this.right = node;
}
} else {
System.out.println("不允许有相同的值");
}
}
// 对加入的数据进行处理,即中序遍历这个最终的二叉排序树
public void traveral_tree() {
// 第一步判断链表是不是为空放到调用里面
if (this.left != null) {
this.left.traveral_tree();// 先遍历左子树
}
System.out.println(this);// 遍历这个父节点
if (this.right != null) {
this.right.traveral_tree();// 先遍历右子树
}
}
// 删除结点前的准备工作1:找到要删除的结点
public Node search_deletednode(int data) {
if (this.data == data) {
return this;
} else if (this.data > data) {
// 往左找的时候是不是还要判断一下,到底左子树是不是不为空
if (this.left != null) {
return this.left.search_deletednode(data);
} else {
return null;// 如果为空是不是就是找不到啊
}
} else {
if (this.right != null) {
return this.right.search_deletednode(data);
} else {
return null;
}
}
}
// 删除结点前的准备工作2:找到要删除结点的父节点
public Node search_deleteednodeparent(int data) {
// 如果当前结点的左孩子或者右孩子与要删除的结点的值相同,那么这个当前结点就是要删除结点的父结点
if ((this.left != null && this.left.data == data) || (this.right != null && this.right.data == data)) {
return this;
} else if (this.left != null && this.data > data) {
return this.left.search_deleteednodeparent(data);
} else if (this.right != null && this.data < data) {
return this.right.search_deleteednodeparent(data);
} else {
return null;// 要删除的结点没有父节点
}
}
}
class BinarySortTree {
private Node root;
// 调用添加的方法
public void add(Node node) {
if (root == null) {
// return;
root = node;
} else {
root.add_node(node);
}
}
// 创建一个初始化数组的方法
public void initial(int[] arr) {
for (int i = 0; i < arr.length; i++) {
this.add(new Node(arr[i]));// 从当前对象开始调用添加的方法进行处理
}
}
// 调用遍历的方法
public void traveral() {
if (root == null) {
return;
} else {
root.traveral_tree();
}
}
// 调用查找删除结点的方法
public Node search(int data) {
if (root == null) {
return null;
} else {
return root.search_deletednode(data);
}
}
//调用查找删除结点的父节点
public Node searchparent(int data) {
if(root == null) {
return null;
}else {
return root.search_deleteednodeparent(data);
}
}
//开始删除结点
public void delete(int data) {
if(root == null) {
return;
}else {
Node deletednode=search(data);
//如果得到的要删除的结点是null,说明没有这个要删除的结点
if(deletednode == null) {
return;
}
//否则就是有值,且这个值等于root时
if(root.left == null && root.right == null) {
root = null;
return;
}
//再否则,就是这个点是内部的
Node parent = searchparent(data);
if(deletednode.left == null && deletednode.right == null) {
//这个里面就是表示,如果要删除的结点是叶子结点
if(parent.left != null && parent.left == deletednode) {//parent.left.data == data
parent.left = null;
}else {
parent.right = null;
}
}else if(deletednode.left != null && deletednode.right != null){
//这个里面就是表示,要删除的结点必有两颗子树,删除其实就是用右子树最小或者左子树最大的点覆盖父节点。
int replacedata=findmin(deletednode.left);
deletednode.data = replacedata;
}else {
//要删除的结点有一颗子树,且这个要被删除的结点的左子树不为空
if(deletednode.left != null) {
//下面表示若这个被删除的结点是这个父节点的左孩子
if(parent.left != null) {
parent.left = deletednode.left;
//下面表示若这个被删除的结点是这个父节点的右孩子
}else {
parent.right=deletednode.left;
}
//要删除的结点有一颗子树,且这个要被删除的结点的右子树不为空
}else {
if(parent.left != null) {
parent.left = deletednode.right;
}else {
parent.right = deletednode.right;
}
}
}
}
}
//找出这个被删除结点右子树中最小的数,删除这个最小值的结点,并返回这个值。最后用这个返回的值来覆盖被删除的值
public int findmin(Node node) {
Node temp = node;//将这个点先给一个辅助变量
//注意传入的这个结点就是要被删除的结点的左孩子结点
while(temp.right != null) {
temp = temp.right;
}
//找到右子树中的最小的结点,此时temp就指向这个结点
delete(temp.data);//我们根据删除叶子结点的方法删除它,其实走的就是删除方法的第一步
return temp.data;//最后我们将这个值返回出来
}
}