Java实现二叉搜索树

前言

在做算法导论第12章的习题时,有一些习题需要用到二叉搜索树的数据结构,为了方便,我将其用Java实现了这个数据结构。

Talk is cheap,show me the code.我就闲话少说了,代码如下。

Java代码实现二叉搜索树数据结构

package hanxl.insist.twelvechapter;

import java.util.Stack;

/**
 * 搜索二叉树
 */
public class BinarySearchTree {
	
	private TreeNode root;
	
	/**
	 * 将数组构建成一个二叉搜索树
	 * @param arr
	 */
	public BinarySearchTree(int[] arr) {
		for (int i : arr)
			insert(i);
	}

	/**
	 * 将给定的元素插入树中
	 * @param e
	 */
	public void insert(Integer e) {
		TreeNode insertPosition = root;
		TreeNode insertPositionParent = null; //记录待插入位置的父节点
		
		while ( insertPosition != null ) {
			insertPositionParent = insertPosition;
			if ( e < insertPosition.item )
				insertPosition = insertPosition.left;
			else
				insertPosition = insertPosition.right;
		}
		
		TreeNode insertPoint = new TreeNode(null, e, null, insertPositionParent);
		if ( insertPositionParent == null ) //树是空的情况
			root = insertPoint;
		else if ( e < insertPositionParent.item )
			insertPositionParent.left = insertPoint;
		else
			insertPositionParent.right = insertPoint;
	}
	
	/**
	 * 将给定的元素从树中删除
	 */
	public void delete(Integer num) {
		TreeNode delNode = search(root, num);
		if ( delNode.right == null )
			transplant(delNode, delNode.left);
		else if ( delNode.left == null )
			transplant(delNode, delNode.right);
		else {
			//无论minimum是不是delNode的右孩子,minimum都会与delNode交换
			//只不过在不是的这种情况下,minimum首先要与自己的右孩子进行交换,然后在重新定义minimum的右孩子
			TreeNode minimum = minimum(delNode.right);
			if(minimum.p != delNode) {
				transplant(minimum, minimum.right);
				minimum.right = delNode.right;
				minimum.right.p = minimum;
			}
			transplant(delNode, minimum);
			minimum.left = delNode.left;
			minimum.left.p = minimum;
		}
	}
	
	/**
	 * 用一颗以tmpNode为根的子树来替换一棵以delNode为根的子树
	 * 结点delNode的父亲就变为tmpNode的父亲,并且最后tmpNode
	 * 成为delNode的父亲的相应孩子。
	 */
	private void transplant(TreeNode delNode, TreeNode tmpNode) {
		if(delNode.p == null)
			root = tmpNode;
		if(delNode == delNode.p.left)
			delNode.p.left = tmpNode;
		else
			delNode.p.right = tmpNode;
		if(tmpNode != null)
			tmpNode.p = delNode.p;
	}

	/**
	 * 在给定的节点及其后代中查询key
	 * @return 如果查询到关键字则返回它,否则返回Null
	 */
	public TreeNode search(TreeNode node, Integer key) {
		if ( node == null || node.item == key )
			return node;
		else if ( node.item < key )
			return search(node.right, key);
		else
			return search(node.left, key);
	}
	
	/**
	 * 获取给定节点的前驱
	 */
	public TreeNode predecessor(TreeNode node) {
		//如果节点有左孩子,它的前驱一定为左子树中的最大值
		if (node.left != null)
			return maximum(node.left);
		
		TreeNode parent = node.p;
		// 如果节点是其父亲的左孩子,那么其前驱一定是遇到的第一个节点是其父亲的右孩子
		while (parent != null && node == parent.left) {
			node = parent;
			parent = parent.p;
		}
		
		//如果节点是其父亲的右孩子,它的前驱一定是它的父亲
		return parent;
	}
	
	/**
	 * 获取给定节点的后继
	 */
	public TreeNode successor(TreeNode node) {
		if (node.right != null)
			return minimum(node.right);
		
		TreeNode parent = node.p;
		while (parent != null && node == parent.right) {
			node = parent;
			parent = parent.p;
		}
		
		return parent;
	}
	
	/**
	 * 获取给定节点及其子树中的最小值
	 * @return
	 */
	public TreeNode minimum(TreeNode node) {
		TreeNode minimum = node;
		while ( minimum.left != null )
			minimum = minimum.left;
		return minimum;
	}
	
	/**
	 * 获取给定节点及其子树中的最大值
	 * @return
	 */
	public TreeNode maximum(TreeNode node) {
		TreeNode maximum = node;
		while ( maximum.right != null )
			maximum = maximum.right;
		return maximum;
	}
	
	/**
	 * 非递归版本的中序遍历
	 */
	public void inorderTreeWalk() {
		Stack<TreeNode> stack = new Stack<TreeNode>(); //这里我用Java.util包中自带的栈
		loadLeftNode(root, stack);
		System.out.print("中序遍历的结果: ");
		while ( !stack.isEmpty() ) {
			TreeNode currentNode = stack.pop();
			System.out.print(currentNode.item + "  ");
			currentNode = currentNode.right;
			loadLeftNode(currentNode, stack);
		}
		System.out.println();
	}


	/**
	 * 加载给定节点的所有后代中的左节点到栈中,直到叶子
	 * 节点为止
	 * @param stack 
	 */
	private void loadLeftNode(TreeNode node, Stack<TreeNode> stack) {
		TreeNode temp = node;
		while ( temp != null ) {
			stack.push(temp);
			temp = temp.left;
		}
	}


	public static class TreeNode {
        Integer item;
        TreeNode left;
        TreeNode right;
        TreeNode p;

        TreeNode(TreeNode left, Integer element, TreeNode right, TreeNode p) {
            this.item = element;
            this.left = left;
            this.right = right;
            this.p = p;
        }
    }
	
	public TreeNode getRoot() {
		return root;
	}
}

测试数据结构的代码

public static void main(String[] args) {
		int[] a = { 23, 45, 12, 56, 32, 78, 100, 3, 90, 678, 2, 4, 8, 92, 67, 49 };
		BinarySearchTree tree = new BinarySearchTree(a);
		
		tree.inorderTreeWalk(); //中序遍历树
		
		System.out.println(tree.search(tree.getRoot(), 12)); //在树中查找给定的关键字
		
		System.out.println("树中的最小值为:" + tree.minimum(tree.getRoot()).item);
		
		System.out.println("树中的最大值为:" + tree.maximum(tree.getRoot()).item);
		
		System.out.println("树根为:" + tree.getRoot().item + " 树根的前驱为:" + tree.predecessor(tree.getRoot()).item);
		
		System.out.println("树根为:" + tree.getRoot().item + " 树根的后继为:" + tree.successor(tree.getRoot()).item);
		
		tree.delete(100);
		tree.inorderTreeWalk(); //中序遍历树
		
	}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
做一门精致,全面详细的 java数据结构与算法!!!让天下没有难学的数据结构,让天下没有难学的算法,不吹不黑,我们的讲师及其敬业,可以看到课程视频,课件,代码的录制撰写,都是在深夜,如此用心,其心可鉴,他不掉头发,谁掉头发???总之你知道的,不知道的,我们都讲,并且持续更新,走过路过,不要错过,不敢说是史上最全的课程,怕违反广告法,总而言之,言而总之,这门课你值得拥有,好吃不贵,对于你知识的渴求,我们管够管饱话不多说,牛不多吹,我们要讲的本门课程内容:稀疏数组、单向队列、环形队列、单向链表、双向链表、环形链表、约瑟夫问题、栈、前缀、中缀、后缀表达式、中缀表达式转换为后缀表达式、递归与回溯、迷宫问题、八皇后问题、算法的时间复杂度、冒泡排序、选择排序、插入排序、快速排序、归并排序、希尔排序、基数排序(桶排序)、堆排序、排序速度分析、二分查找、插值查找、斐波那契查找、散列、哈希表、二叉树、二叉树与数组转换、二叉排序树(BST)、AVL树、线索二叉树、赫夫曼树、赫夫曼编码、多路查找树(B树B+树和B*树)、图、图的DFS算法和BFS、程序员常用10大算法、二分查找算法(非递归)、分治算法、动态规划算法、KMP算法、贪心算法、普里姆算法、克鲁斯卡尔算法、迪杰斯特拉算法、弗洛伊德算法马踏棋盘算法。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值