Binary Search Tree实现

一个BST tree demo,最难的部分是delete()方法。在要删除节点有左右两个子树的时候,不是采用删除该节点,将左子树或右子树提升,同时将一个子树挂到另一个子树下边。

而是直接将右子树的最小节点的值赋给要删除的节点,同时将右子树最小节点删除(采用递归算法)。这样使树更平衡些。

另外,方法返回值类型什么时候采用boolean,什么时候不返回,抛异常也是一个需要考虑的问题。

package indi.tom.dataStructure.tree;

import org.junit.Test;



/**
 * @Author: Tom
 * @Date: 2021年1月3日 下午8:43:56
 * @Version: 1.0
 * @Description: A demo of BST, including search, add, delete function.
 */
public class BinarySearchTreeTest {

	@Test
	public void test01() throws ValueNotFoundException {
		Node node12 = new Node(12);

		Node node8 = new Node(8);
		Node node18 = new Node(18);
		node12.setLeft(node8);
		node12.setRight(node18);
		
		Node node5 = new Node(5);
		Node node10 = new Node(10);
		node8.setLeft(node5);
		node8.setRight(node10);
		
		Node node15 = new Node(15);
		Node node22 = new Node(22);
		node18.setLeft(node15);
		node18.setRight(node22);
		
		Node node4 = new Node(4);
		Node node6 = new Node(6);
		node5.setLeft(node4);
		node5.setRight(node6);
		
		Node node9 = new Node(9);
		Node node11 = new Node(11);
		node10.setLeft(node9);
		node10.setRight(node11);
		Node node13 = new Node(13);
		Node node17 = new Node(17);
		node15.setLeft(node13);
		node15.setRight(node17);
		binarysearchtree binarysearchtree = new binarysearchtree(node12);

//		binarysearchtree.add(7);
		System.out.println("*******");
//		binarysearchtree.inOrder();
//		binarysearchtree.delete(8);
//		binarysearchtree.inOrder();
		binarysearchtree.delete(9);
		binarysearchtree.delete(10);
		binarysearchtree.inOrder();

	}
	
	@Test
	public void test02() {
//		
//		for (int i = 4; i < 20; i++) {
//			binarysearchtree.add(i);
//		}
//		binarysearchtree.inOrder();
	}

	class Node {

		private int value;
		private Node left, right;

		public Node(int value) {
			super();
			this.value = value;
		}

		public int getValue() {
			return value;
		}

		public void setValue(int value) {
			this.value = value;
		}

		public Node getLeft() {
			return left;
		}

		public void setLeft(Node left) {
			this.left = left;
		}

		public Node getRight() {
			return right;
		}

		public void setRight(Node right) {
			this.right = right;
		}

		// InOrder traverse
		public void inOrder() {
			if (this.left != null) {
				this.left.inOrder();
			}
			System.out.println(value);
			if (this.right != null) {
				this.right.inOrder();
			}
		}

		// search
		public Node search(int value) {
			Node target = null;
			if (this.value == value)
				return this;
			if (this.left != null) {
				target = this.left.search(value);
				if (target != null)
					return target;
			}
			if (this.right != null) {
				target = this.right.search(value);
				if (target != null)
					return target;
			}
			return null;
		}

		// add

		public Node add(int value) {
			Node target = new Node(value);
			if (this.value <= value) {
				if (this.right == null) {
					return this.right = target;
				} else {
					return this.right.add(value);
				}
			} else {
				if (this.left == null) {
					return this.left = target;
				} else {
					return this.left.add(value);
				}
			}
		}

		@Override
		public String toString() {
			return "Node [value=" + value + "]";
		}
		
		

	}

	class binarysearchtree {
		Node root;

		public binarysearchtree(Node root) {
			super();
			this.root = root;
		}

		// In order traverse
		public void inOrder() {
			root.inOrder();
		}

		// BST search
		public Node search(int value) {
			if (root == null)
				return null;
			return root.search(value);
		}

		// BST add
		public Node add(int value) {
			if (root == null)
				return root = new Node(value);
			return root.add(value);
		}

	
		/**
		 * 
		* @Description: Delete the node with given value from the tree ****Difficult*****
		* @param  value The Node value to be deleted
		* @return  no return value
		* @throws ValueNotFoundException when the given value is not found in the tree.
		 */
		public void delete(int value) throws ValueNotFoundException {
			//1. root is null or not found in the tree
			if (root == null)
				throw new ValueNotFoundException("This is a blank tree");
			Node searchResultNode = search(value);
			if (searchResultNode == null)
				throw new ValueNotFoundException("The given value is not found");
			Node parent = searchParent(root, value);
			System.out.println("searchResultNode: " + searchResultNode);
			System.out.println("parentNode:" + parent);
			// 2. root node is the one that has the value
			if (parent == null) {
				if (root.getLeft() == null && root.getRight() == null) {
					root = null;
				} else if (root.getLeft() != null && root.getRight() != null) {
					int minValue = getAndDeleteRightTreeMinValue(root.getRight());
					root.setValue(minValue);
				} else if (root.getLeft() != null && root.getRight() == null) {
					this.root = root.getLeft();
				} else if (root.getLeft() == null && root.getRight() != null) {
					this.root = root.getRight();
				}
			//3. the value exists being held by an non-root node
			} else {
				//3.1 searchResultNode is a leaf node, remove it directly
				if (searchResultNode.getLeft() == null && searchResultNode.getRight() == null) {
					if (parent.getLeft() == searchResultNode) {
						parent.setLeft(null);
					} else {
						parent.setRight(null);
					}
				//3.2 both the left and right child of searchResultNode is not null
                //在要删除节点有左右两个子树的时候,不是采用删除该节点,将左子树或右子树提升,同时将一个子树挂到另一个子树下边。

//而是直接将右子树的最小节点的值赋给要删除的节点,同时将右子树最小节点删除(采用递归算法)。这样使树更平衡些。
				} else if (searchResultNode.getLeft() != null && searchResultNode.getRight() != null) {
					int minValue = getAndDeleteRightTreeMinValue(searchResultNode.getRight());
					searchResultNode.setValue(minValue);
				//3.3 left child is not null
				} else if (searchResultNode.getLeft() != null && searchResultNode.getRight() == null) {
					parent.setLeft(searchResultNode.getLeft());
				//3.4 right child is not null
				} else {
					parent.setRight(searchResultNode.getRight());
				}
			}


		}

		// get the min value in the right subtree and remove the corresponding node
		private int getAndDeleteRightTreeMinValue(Node node) throws ValueNotFoundException {

			while (node.getLeft() != null) {
				node = node.getLeft();
			}

			int minimal = node.getValue();
			// delete the minimal node
			delete(minimal);
			return minimal;

		}

		private Node searchParent(Node node, int value) {

			if (node.getValue() == value)
				return null;
			Node target = null;
			if (node.getLeft() != null) {
				if (node.getLeft().getValue() == value) {
					return node;
				} else {
					target = searchParent(node.getLeft(), value);
					if (target != null)
						return target;
				}

			}
			if (node.getRight() != null) {
				if (node.getRight().getValue() == value) {
					return node;
				} else {
					target = searchParent(node.getRight(), value);
					if (target != null)
						return target;
				}

			}

			return null;
		}
	}
	
	class ValueNotFoundException extends Exception{
		
		public ValueNotFoundException() {
			super();
		}
		
		public ValueNotFoundException(String message) {
			super(message);
		}
		
		public ValueNotFoundException(String message, Throwable cause) {
			super(message, cause);
		}
	}

}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值