树论之二叉搜索树

二叉搜索树

二叉查找树(Binary Search Tree),(又:二叉搜索树,二叉排序树)它或者是一棵空树,或者是具有下列性质的二叉树: 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值; 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值; 它的左、右子树也分别为二叉排序树。

二叉搜索树操作

  • 因为二叉树搜索树的特点,我们插入一个元素必然需要从根节点开始查找整个树,直到找到准确的位置
  • 二叉搜索树查询很快logn
  • 二叉搜索树的删除
  1. 如果要删除的节点是叶子节点 直接删除,父节点对应子树设为null
  2. 如果要删除的节点只有一个子树,父节点指向当前节点的子树。
  3. 如果要删除的节点有2个子树,则先找到当前节点的后继节点,把后继节点的值赋值给当前节点。删除后继节点,因为后继节点肯定不会有2个子树。

代码再现

public class MyBinarySeachTree {

	private TreeNode root;
	
	static class TreeNode {
		private TreeNode left;//左节点
		private TreeNode right;//右节点
		private TreeNode parent;//父节点
		private int data;//数据值
		private boolean position = false;//表示左边
		public TreeNode(int data) {
			this.data = data;
		}
	}
	
	public MyBinarySeachTree(int data) {
		root = new TreeNode(data); 
	}
	
	/**
	 * 正常插入法
	 * @param data
	 */
	public void insert(int data) {
		TreeNode node = new TreeNode(data);
		TreeNode pa = root.right;
		if( node.data >= root.data) {
			pa = root.right;
		}else{
			pa = root.left;
		}
		while( true ) {
			if( pa == null && node.data >= root.data  ) {
				root.right = node;
				node.parent = root;
				node.position = true;
				break;
			}else if(pa == null && node.data < root.data) {
				root.left = node;
				node.parent = root;
				break;
			}
			if( node.data >= pa.data){
				if( pa.right != null) {
					pa = pa.right;
					continue;
				}
				pa.right = node;
				node.parent = pa;
				node.position = true;
				break;
			}else if(node.data < pa.data ){
				if( pa.left != null) {
					pa = pa.left;
					continue;
				}
				pa.left = node;
				node.parent = pa;
				break;
			} 
		}
		
	}
	
	/**
	 * 递归插入法
	 * @param root
	 * @param data
	 */
	public void insert(TreeNode root , int data) {
		if( data > root.data) {
			if(root.right ==null) {
				TreeNode node = new TreeNode(data);
				root.right = node;
				node.parent = root;
				node.position = true;
				return;
			}
			insert(root.right, data);
		}else {
			if(root.left ==null) {
				TreeNode node = new TreeNode(data);
				root.left = node;
				node.parent = root;
				return;
			}
			insert(root.left, data);
		}
	}
	
	public TreeNode search(TreeNode root , int data) {
		if(root == null) {
			System.out.println("没有找到");
			return null;
		}
		if( data > root.data) {
			return search(root.right, data);
		}else if(data < root.data ) {
			return search(root.left, data);
		}else{
			System.out.println("找到节点了");
			return root; 
		}
	}
	
	private TreeNode findNextNode(TreeNode node) {
		TreeNode parent = node;
		while(parent.left != null) {
			parent = parent.left;
		}
		return parent;
	}
	
	/**
	 *        9
	 *    7       11
	 *  5   8   10     16(X)
	 *2   6         12    24
	 *                 19    26
	 *                    20    28
	 * 
	 * 1.要删除的结点是叶子结点 O(1)
     * 2.要删除的结点只有一个子树(左或者右)O(1)
     * 3.要删除的结点有两颗子树:找后继结点,而且后继结点的左子树一定为空。
	 * 
	 * 
	 * @param data
	 */
	public void remove(int data) {
		TreeNode node = search(root, data);
		remove(node);
	}
	
	private void remove(TreeNode node) {
		if( node !=null ) {
			 //先判断是否存在左右子树
			if(node.left ==null || node.right == null) {
				if(node.left != null && node.position==false) node.parent.left = node.left;//要删除节点的左子树不为空,并且当前节点是父节点的左子树
				else if(node.left != null && node.position==true) node.parent.right = node.left;//要删除节点的左子树不为空,并且当前节点是父节点的右子树
				else if(node.right != null && node.position==false) node.parent.left = node.right;//要删除节点的右子树不为空,并且当前节点是父节点的左子树
				else if(node.right != null && node.position==true) node.parent.right = node.right;//要删除节点的右子树不为空,并且当前节点是父节点的右子树
				else if(node.position==false) node.parent.left = null; //当前节点是父节点的左子树
				else node.parent.right = null; //当前节点是父节点的右子树
				//移除当前节点
				node = null;
			}else{//查找当前节点的后继节点
				TreeNode treeNode = findNextNode(node.right);
				node.data = treeNode.data;
				remove(treeNode);
			}
		}
	}
	
	public void print() {
		show(root);
		System.out.println("");
	}
	
	private void show(TreeNode node) {
		if(node == null) {
			return;
		}
		show(node.left);
		System.out.print(node.data+ " ");
		show(node.right);
	}
	
	public static void main(String[] args) {
		int data[] = {9,7,11,5,8,10,16,2,6,12,24,19,26,20,28};
		MyBinarySeachTree root = new MyBinarySeachTree(data[0]);	//第一个点作为跟结点
		for(int i = 1 ; i < data.length ; i ++) {
			//root.insert(root, data[i]);
			root.insert(data[i]);
		}
		root.print();
		root.remove(16);
		System.out.println("删除节点:"+16);
		root.print();
	}
	
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值