java实现二叉查找树以及相关操作

package com.dataStructure.searchTree;

/**
 * 二叉查找树,对于其中的任何一个结点x,如果y是x左子树中的一个结点,那么y的关键字一定不大于x的关键字;
 * 如果y是x右子树中的一个结点,那么y的关键字一定不小于x的关键字
 */
public class BinarySearchTree {
	private static Node root = null;
	private class Node{
		private int key;
		private Node leftChild;
		private Node rightChild;
		private Node parent;
		public Node(int key, Node leftChild, Node rightChild, Node parent){
			this.key = key;
			this.leftChild = leftChild;
			this.rightChild = rightChild;
			this.parent = parent;
		}
	}
	public static Node getRoot(BinarySearchTree tree){
		return root;
	}
	/**
	 * 插入关键字key
	 */
	public  void  insert( int key) {
		Node y = null;
		Node x = root;//指向根结点
		Node node = new Node(key, null, null, null);
		//while循环结束的时候,x指向空结点,y指向待插入结点的双亲
		while(x != null){
			y = x;//y指向双亲结点
			if(node.key < x.key){
				x = x.leftChild;
			}else{
				x = x.rightChild;
			}
		}
		//将待插入结点的双亲赋值为y结点
		node.parent = y;
		//如果y为空,说明树为空
		if(y == null){
			root = node;
		}else{
			//根据关键字的大小,将y插入到合适的地方
			if (node.key < y.key) {
				y.leftChild = node;
			}else{
				y.rightChild = node;
			}
		}
	}
	/**
	 * 删除关键字key所对应的结点,对应3种不同的情况
	 * 1、结点没有孩子,则可以直接删除该结点,将该结点的双亲结点对应的孩子指针置为null
	 * 2、结点只有一个孩子,则可以将结点的孩子直接连到结点的双亲结点上,作为双亲结点的孩子,然后删除该结点
	 * 3、结点有两个孩子,则需要删除的是结点的后继结点,将后继结点的数据拷贝到该结点内,同时后继结点的孩子作为后继结点双亲结点的孩子,
	 * 		因为后继结点最后只有一个子女
	 */
	public void delete(int key){
		Node z = tree_search(root, key);
		if(z == null){
			return;
		}else{
			Node x = new Node(0, null, null, null);
			Node y = new Node(0, null, null, null);
			if(z.leftChild == null || z.rightChild == null){
				y = z;
			}else{
				y = tree_successor(z);
			}
			if(y.leftChild != null){
				x = y.leftChild;
			}else{
				x = y.rightChild;
			}
			if(x != null){
				x.parent = y.parent;
			}
			if(y.parent == null){
				root = x;
			}else{
				if(y==(y.parent).leftChild){
					(y.parent).leftChild = x;
				}else{
					(y.parent).rightChild = x;
				}
			}
			if(y != z){
				z.key = y.key;
			}
		}
	}
	/**
	 * 判断二叉查找树是否为空
	 */
	public static  boolean isEmpty(BinarySearchTree tree){
		if (BinarySearchTree.root == null) {
			return true;
		}else{
			return false;
		}
	}
	/**
	 * 中序遍历二叉查找树
	 */
	public static void inorder_tree_walk(Node tree){
		if(tree != null){
			inorder_tree_walk(tree.leftChild	);
			System.out.print(tree.key + "  " );
			inorder_tree_walk(tree.rightChild);
		}
	}
	/**
	 * 查找关键字为key的结点(递归查找)
	 */
	public Node tree_search(Node root, int key){
		if(root == null || key == root.key){
			return root;
		}
		if(root.key < key){
			return tree_search(root.rightChild, key);
		}else{
			return tree_search(root.leftChild, key);
		}
	}
	/**
	 * 查找关键字为key的结点(非递归查找)
	 */
	public Node iterative_tree_search(Node root, int key){
		while(root != null && key!= root.key){
			if(key< root.key){
				root = root.leftChild;
			}else{
				root = root.rightChild;
			}
		}
		return root;
	}
	/**
	 * 查找最小关键字元素,查找方法:
	 * 从根节点开始,沿着各结点的左孩子指针查找下去,直至遇到空为止
	 */
	public Node tree_minimum(Node root){
		while(root.leftChild != null){
			root = root.leftChild;
		}
		return root;
	}
	/**
	 * 查找最大关键字元素
	 */
	public Node tree_maximum(Node root){
		while(root.rightChild != null){
			root = root.rightChild;
		}
		return root;
	}
	/**
	 * 查找元素的后继
	 */
	public Node tree_successor(Node node){
		//如果结点的右子树不为空,则x的后继即为右子树中的最左结点,也即右子树中的最小结点
		if(node.rightChild != null){
			return tree_minimum(node.rightChild);
		}
		//如果结点的右子树为空,且有一个后继y, 则y是该结点的最低祖先节点,且y的左儿子也是该结点的祖先
		Node yNode = node.parent;
		while(yNode != null && node == yNode.rightChild){
			node = yNode;
			yNode = yNode.parent;
		}
		return yNode;
	}
	/**
	 * 查找元素的前驱
	 */
	public Node tree_precorsor(Node node){
		if(node.leftChild != null){
			return tree_maximum(node.leftChild);
		}
		Node yNode = node.parent;
		while(yNode!=null && node == yNode.leftChild){
			node = yNode;
			yNode = yNode.parent;
		}
		return yNode;
	}
	/**
	 * 测试
	 */
	public static void main(String[] args) {
		//构建二叉查找树
		BinarySearchTree tree = new BinarySearchTree();
		int[] keys = {18, 5, 6, 3, 12, 20, 2, 4, 13, 9};
		for(int i = 0;i<keys.length; i++){
			tree.insert(keys[i]);
		}
		inorder_tree_walk(root);
		System.out.println();
		//查找关键字18
		Node _18Node = tree.tree_search(root, 18);
		if(_18Node == null){
			System.out.println("不存在关键字18");
		}else{
			System.err.println("查找到关键字18");
		}
		//查找关键字19
		Node _19Node = tree.iterative_tree_search(root, 19);
		if(_19Node == null){
			System.out.println("不存在关键字19");
		}else{
			System.err.println("查找到关键字19");
		}
		//查找最小关键字元素
		Node minNode = tree.tree_minimum(root);
		System.out.println("最小值为:" + minNode.key);
		//查找最大关键字元素
		Node maxNode = tree.tree_maximum(root);
		System.out.println("最大值为:" + maxNode.key);
		//查找元素13的后继
		Node _13Node = tree.tree_search(root, 13);
		Node _13Successor = tree.tree_successor(_13Node);
		System.out.println("元素13的后继元素的关键字为:" + _13Successor.key);
		//查找元素13的前驱
		Node _13Precursor = tree.tree_precorsor(_13Node);
		System.out.println("元素13的前驱元素的关键字为:" + _13Precursor.key);
		//删除元素13,对应第一种情况
		tree.delete(13);
		inorder_tree_walk(root);
		System.out.println();
		//删除关键字19,对应找不到该结点的情况
		tree.delete(19);
		inorder_tree_walk(root);
		System.out.println();
		//删除关键字6,对应第二种情况
		tree.delete(6);
		inorder_tree_walk(root);
		System.out.println();
		//删除元素5,对应第三种情况
		tree.delete(5);
		inorder_tree_walk(root);
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值