二叉查找树常见的操作(Java实现)

学习记录

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;//最后我们将这个值返回出来
	} 
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值