搜索树

搜索树
概念:二叉搜索树又称二叉排序树,它或者是一棵空树**,或者是具有以下性质的二叉树:
1. 若它的左子树不为空,则左子树上所有节点的值都小于根节点的值
2. 若它的右子树不为空,则右子树上所有节点的值都大于根节点的值
3. 它的左右子树也分别为二叉搜索树
查找 插入 删除

public class BinarySearchTree {
	public static class Node {
		int key;
		Node left;
		Node right;

		public Node(int key) {
			this.key = key;
		}
	}

	private Node root = null;

	/**
	 * 在搜索树中查找 key,如果找到,返回 key 所在的节点
	 * 否则返回null
	 * @param  key [description]
	 * @return     [description]
	 */
	public Node search(int key) {
		Node cur = root;
		while(cur != null) {
			if (key == cur.key) {
				return cur;
			}else if (key < cur.key) {
				cur = cur.left;
			}else {
				cur = cur.right;
			}
		}

		return null;
	}

	/**
	 * 插入
	 * @param  key [description]
	 * @return true  表示插入成功
	 *         false 表示插入失败   
	 */
	public boolean insert(int key) {
		if (root == null) {
			root = new Node(key);
			return true;
		}

		Node cur = root;
		Node parent = null;
		while(cur != null) {
			if (key == cur.key) {
				return false;
			}else if (key < cur.key) {
				parent = cur;
				cur = cur.left;
			}else {
				parent = cur;
				cur = cur.right;
			}
		}

		Node node = new Node(key);
		if (key < parent.key) {
			parent.left = node;
		}else {
			parent.right = node;
		}
		return true;
	}

	/**
	 * 删除
	 * @param  key [description]
	 * @return  true  表示删除成功
	 *          false 表示删除失败 
	 */
	public boolean remove(int key) {
		Node cur = root;
		Node parent = null;
		while(cur != null) {
			if (key == cur.key) {
				removeNode(parent,cur);
				return true;
			}else if (key < cur.key) {
				parent = cur;
				cur = cur.left;
			}else {
				parent = cur;
				cur = cur.right;
			}
		}

		return false;
	}

	private void removeNode(Node parent, Node cur) {
		if (cur.left == null) {
			if (cur == root) {
				root = cur.right;
			}else if (cur == parent.left) {
				parent.left = cur.right;
			}else {
				parent.right = cur.right;	
			}
		}else if (cur.right == null) {
			if (cur == root) {
				root = cur.left;
			}else if (cur == parent.left) {
				parent.left = cur.left;
			}else {
				parent.right = cur.left;
			}
		}else {
			Node goatParent = cur;
			Node goat = cur.right;
			while(goat.left != null) {
				goatParent = goat;
				goat = goat .left;
			}

			cur.key = goat.key;

			if (goat == goatParent.left) {
				goatParent.left = goat.right;
			}else {
				goatParent.right = goat.right;
			}
		}
	}

	public static void main(String[] args) {
		//1. 创建搜索树
		//2. 随机插入
		//3. 打印前序 + 中序遍历
		//4. 查找
		BinarySearchTree tree = new BinarySearchTree();
		int[] keys = {3,9,7,4,1,6,2,8,5};
		for (int key : keys) {
			System.out.println(tree.insert(key));
		}

		System.out.println("插入重复数据");
		System.out.println(tree.insert(7));

		System.out.println("前序遍历");
		preOrder(tree.root);

		System.out.println("中序遍历");
		inOrder(tree.root);

		System.out.println(tree.search(7).key);
		System.out.println(tree.search(8).key);
		System.out.println(tree.search(5).key);
	}

	private static void inOrder(Node node) {
		if (node != null) {
			inOrder(node.left);
			System.out.println(node.key);
			inOrder(node.right);
		}
	}

	private static void preOrder(Node node) {
		if (node != null) {
			System.out.println(node.key);
			preOrder(node.left);
			preOrder(node.right);
		}
	}
}

泛型类支持的搜索树

import java.unil.*;

public class BSTree<K extends Comparable<K>, V> {
	private static class Entry<K, V> {
		private K key;
		private V value;
		private Entry<K, V> left = null;
		private Entry<K, V> right = null;

		private Entry(K key, V value) {
			this.key = key;
			this.value = value;
		}

		@Override
		public String toString() {
			return String.format("{%s=%s}", key, value);
		}
	}

	private Entry<K, V> root = null;

	public V get(K key) {
		Entry<K, V> cur = root;
		while (cur != null) {
			int r = key.compareTo(cur.key);
			if (r == 0) {
				return cur.value;
			}else if (r < 0) {
				cur = cur.left;
			}else {
				cur = cur.right;
			}
		}

		return null;
	}

	public V put(K key, V value) {
		if (root == null) {
			root = new Entry<>(key, value);
			return null;
		}

		Entry<K, V> parent = null;
		Entry<K, V> cur = root;
		while(cur != null) {
			int r = key.compareTo(cur.key);
			if (r == 0) {
				V oldValue = cur.value;
				cur.value = value;
			}else if (r < 0) {
				parent = cur;
				cur = cur.left;
			}else {
				parent = cur;
				cur = cur.right;
			}
		}

		Entry<K, V> entry = new Entry<>(key, value);
		if (key.compareTo(parent.key) < 0) {
			parent.left = entry;
		}else {
			parent.right = entry;
		}

		return null;
	}

	public V remove(K key) {
		Entry<K, V> parent = null;
		Entry<K, V> cur = root;
		while(cur != null) {
			int r = key.compareTo(cur.key);
			if (r == 0) {
				V oldValue = cur.value;
				removeEntry(parent,cur);
				return oldValue;
			}else if (r < 0) {
				parent = cur;
				cur = cur.left;
			}else {
				parent = cur;
				cur = cur.right;
			}
		}

		return null;
	}

	private void removeEntry(Entry<K, V> parent, Entry<K, V> cur) {
		if (cur.left == null) {
			if (cur == root) {
				root = cur.right;
			}else if (cur == parent.left) {
				parent.left = cur.right;
			}else {
				parent.right = cur.right;
			}
		}else if (cur.right == null) {
			if (cur == root) {
				root = cur.left;
			}else if (cur == parent.left) {
				parent.left = cur.left;
			}else {
				parent.right = cur.left;
			}
		}else {
			Entry<K, V> gParent = cur;
			Entry<K, V> goat = cur.left;
			while(goat.right != null) {
				gParent = goat;
				goat = goat.right;
			}
			cur.key = goat.key;
			cur.value = goat.value;
			if (goat == gParent.left) {
				gParent.left = goat.left;
			}else {
				gParent.right = goat.left;
			}
		}
	}

	public static interface Function<T> {
		void apply(T entry);
	}

	public static <K, V> void preOrderTraversal(Entry<K, V> node, Function<Entry<K, V>> func) {
		if (node != null) {
			func.apply(node);
			preOrderTraversal(node.left, func);
			preOrderTraversal(node.right, func);
		}
	}

	public static <K, V> void inOrderTraversal(Entry<K, V> node, Function<Entry<K, V>> func) {
		if (node != null) {
			inOrderTraversal(node.left, func);
			func.apply(node);
			inOrderTraversal(node.right, func);
		}
	}

	public void print() {
		System.out.println("前序遍历:");
		preOrderTraversal(root, (n) -> {
			System.out.print(n.key + " ");
		});
		System.out.println();
		System.out.println("中序遍历:");
		inOrderTraversal(root, (n) -> {
			System.out.print(n.key + " ");
		});
		System.out.println();
	}

	public static void main(String[] args) {
		BSTree<Integer, String> tree = new BSTree<>();
		int count = 0;
		Random random = new Random(20200529);
		for (int i = 0; i < 20; i++) {
			int key = random.nextInt(200);
			String value = String.format("value of %d", key);
			if (tree.put(key. value) == null) {
				count++;
			}
		}
		System.out.println("一共插入 " + count + " 个结点");
		tree.print();
	}
} 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值