二叉排序树

概念

    二叉排序树,又称二叉查找树。它或者是一棵空树,或者是具有下列性质的二叉树:
①若它的左子树不空,则左子树上所有节点的值均小于它的根节点的值。
② 若它的右子树不空,则右子树上所有节点的值均大于它的根节点的值。
③ 它的左右子树也分别为二叉排序树。

查找、插入和删除操作

package binaryTree;

public class TreeNode {
	int val;
	TreeNode left;
	TreeNode right;

	TreeNode(int val) {
		this.val = val;
	}
}

举例

package binaryTree;

import java.util.ArrayList;
import java.util.Scanner;

public class BST {

	// 若查找成功p指向该数据元素结点,否则p指向查找路径上访问的最后一个结点;
	private static TreeNode p;

	/**
	 * 查找操作
	 * 
	 * 思路:根据二叉排序树的性质,分左右子树进行递归查找;
	 * 
	 * @param root
	 *            当前结点;
	 * @param f
	 *            当前节点的父结点;
	 * @param p
	 * 
	 * @param key
	 *            关键值
	 */
	private static boolean BST_search(TreeNode root, TreeNode f, int key) {
		if (root == null) {
			p = f;
			return false;
		} else if (key == root.val) {
			p = root;
			return true;
		} else if (key > root.val) {
			return BST_search(root.right, root, key);
		} else {
			return BST_search(root.left, root, key);
		}
	}

	/**
	 * 插入操作;
	 * 
	 * 思路:先查找原二叉树是否存在,不存在插入,存在则不插入;
	 * 
	 * @param key
	 *            关键值
	 */
	private static boolean BST_insert(TreeNode root, int key) {

		p = null;
		if (!BST_search(root, null, key)) { // 不存在,则插入,p是查找的最后一个节点;
			TreeNode node = new TreeNode(key);
			if (p == null) { // 根节点;
				root = node;
			} else if (p.val < key) { // node作为右结点;
				p.right = node;
			} else { // 作为左节点;
				p.left = node;
			}
			return true;
		} else { // 已经存在;
			return false;
		}
	}

	private static void clear() {
		p = null;
	}

	/**
	 * 删除操作;
	 * 分情况:1、待删除的点为叶子结点(直接删除);2、只有左或者右分支(子承父业);3、左右分支都存在(找中序遍历待删结点的前驱或者后继结点代替);
	 * 
	 * @param root
	 *            当前结点;
	 * @param key
	 *            关键字;
	 * @return
	 */
	private static boolean BST_delete(TreeNode root, int key) {
		if (root == null) { // 树为空,则不存在关键字为key的值;
			return false;
		} else {
			if (key == root.val) { // 找到;
				return deleteNode(root);

			} else if (root.val > key) { // 到左子树中去查找;
				return BST_delete(root.left, key);
			} else {// 到右子树中去查找;
				return BST_delete(root.right, key);
			}
		}
	}

	/**
	 * 删除结点;
	 * 
	 * @param root
	 * @return
	 */
	private static boolean deleteNode(TreeNode root) {
		if (root.left == null && root.right == null) { // 叶子结点;
			root = null;

		} else if (root.left == null) {// 左子树为空,则右子树的根结点代替;
			root = root.right;

		} else if (root.right == null) { // 右子树为空,则左子树的根结点代替;
			root = root.left;

		} else { // 左右子树都存在;
			// 首先找到该结点的中序遍历的前驱结点,即左子树的最右端的结点;
			TreeNode f = root;
			TreeNode p = f.left;// 左子树的根结点;
			while (p.right != null) {
				f = p;
				p = p.right;
			}
			// 找到最终的的前驱f;
			root.val = p.val;
			if (f == root) { // 重新连接q的左子树;
				f.left = p.left;
			} else { // 重新连接q的右子树;
				f.right = p.left;
			}
			p = null;

		}
		return true;
	}

	/**
	 * 中序遍历
	 * 
	 * @param root
	 */
	private static void inOrderTraverse(TreeNode root, ArrayList<Integer> list) {
		if (root == null) {
			return;
		}

		inOrderTraverse(root.left, list);
		list.add(root.val);
		inOrderTraverse(root.right, list);

	}

	public static void main(String[] args) {

		TreeNode root = null;
		ArrayList<Integer> list = new ArrayList<Integer>();
		int[] arr = { 80, 56, 92, 34, 60, 86, 101, 22, 49, 58, 72, 42 };

		for (int i : arr) {
			if (root == null) {
				root = new TreeNode(i);// 根节点显示给出单独;;
			} else {
				BST_insert(root, i);
			}
		}

		// 原二叉排序树;
		inOrderTraverse(root, list);
		System.out.println("删除前:"+list);

		// 清空p;
		clear();

		// 删除56这个结点;
		BST_delete(root, 56);

		// 清空List;
		list.clear();
		// 删除后结构没有改变;
		inOrderTraverse(root, list);
		System.out.println("删除结点56后:"+list);

	}
}


运行结果:

多思考,多尝试。
原文地址:https://www.cnblogs.com/LynnMin/p/9504446.html