数据结构(Java语言)——BinarySearchTree简单实现

二叉树的一个重要应用是它们在查找中的使用。使二叉树成为二叉查找树的性质是,对于树中的每个节点X,它的左子树中所有项的值都大于X中的项。注意,这意味着该树所有的元素都可以用某种一致的方式排序。

现在给出通常对二叉查找树进行的操作的简单描述。注意,由于树的递归定义,通常是递归地编写这些操作的例程。因为二叉查找树的平均深度是O(logN),所以一般不必担心栈空间耗尽。

二叉查找树要求所有的项都能够排序。要写出一个一般的类,我们需要提供一个接口来表示这个性质。这个接口就是Comparable,它告诉我们树中的两项总可以使用compareTo()方法进行比较。由此我们可以确定所有可能关系,特别是以compareTo()返回0来替代equal()判断相等。BinarySearchTree类还包含一个嵌套类BinaryNode,用来表示树的节点。

以下是相关代码及实现:

public class BinarySearchTree<AnyType extends Comparable<? super AnyType>> {

	private BinaryNode<AnyType> root;

	private static class BinaryNode<AnyType> {
		AnyType element;
		BinaryNode<AnyType> left;
		BinaryNode<AnyType> right;

		BinaryNode(AnyType theElement) {
			this(theElement, null, null);
		}

		BinaryNode(AnyType theElement, BinaryNode<AnyType> lt,
				BinaryNode<AnyType> rt) {
			element = theElement;
			left = lt;
			right = rt;
		}
	}

	public BinarySearchTree() {
		makeEmpty();
	}

	/**
	 * 使树为空树
	 */
	public void makeEmpty() {
		root = null;
	}

	/**
	 * 该树是否为空树
	 *
	 * @return 是否空
	 */
	public boolean isEmpty() {
		return root == null;
	}

	/**
	 * 该树是否存在含有参数值的节点
	 *
	 * @param value
	 *            元素值
	 * @return 是否含该元素
	 */
	public boolean contains(AnyType value) {
		return contains(value, root);
	}

	/**
	 * 某个节点及它的子节点是否存在含有参数值的节点
	 *
	 * @param value
	 *            元素值
	 * @param node
	 *            节点
	 * @return
	 */
	private boolean contains(AnyType value, BinaryNode<AnyType> node) {
		if (node == null) {
			return false;
		}
		int compareResult = value.compareTo(node.element);
		if (compareResult < 0) { // 插入节点值小于节点值,则递归查找左子树下
			return contains(value, node.left);
		} else if (compareResult > 0) { // 插入节点值大于节点值,则递归查找右子树下
			return contains(value, node.right);
		} else {
			return true;
		}
	}

	/**
	 * 查找该树最小元素值
	 *
	 * @return 最小元素值
	 */
	public AnyType findMin() {
		if (isEmpty()) {
			throw new NullPointerException();
		}
		return findMin(root).element;
	}

	/**
	 * 查找某节点及其子树中的最小元素
	 *
	 * @param node
	 *            父节点
	 * @return 最小元素所在节点
	 */
	private BinaryNode<AnyType> findMin(BinaryNode<AnyType> node) {
		if (node == null) {
			return null;
		} else if (node.left == null) {
			return node;
		}
		return findMin(node.left);
	}

	/**
	 * 查找该树最大元素值
	 *
	 * @return 最大元素值
	 */
	public AnyType findMax() {
		if (isEmpty()) {
			throw new NullPointerException();
		}
		return findMavalue(root).element;
	}

	/**
	 * 查找某节点及其子树中的最大元素
	 *
	 * @param node
	 *            父节点
	 * @return 最大元素
	 */
	private BinaryNode<AnyType> findMavalue(BinaryNode<AnyType> node) {
		if (node == null) {
			return null;
		} else if (node.right == null) {
			return node;
		}
		return findMavalue(node.right);
	}

	/**
	 * 向树中插入某元素
	 *
	 * @param value
	 *            插入元素值
	 */
	public void insert(AnyType value) {
		root = insert(value, root);
	}

	/**
	 * 向某个节点下插入元素
	 *
	 * @param value
	 *            元素值
	 * @param node
	 *            父节点
	 * @return 元素插入的节点
	 */
	private BinaryNode<AnyType> insert(AnyType value, BinaryNode<AnyType> node) {
		if (node == null) {
			return new BinaryNode<AnyType>(value);
		}
		int compareResult = value.compareTo(node.element);
		if (compareResult < 0) {
			node.left = insert(value, node.left);
		} else if (compareResult > 0) {
			node.right = insert(value, node.right);
		}
		return node;
	}

	/**
	 * 向树中删除某元素
	 *
	 * @param value
	 *            元素值
	 */
	public void remove(AnyType value) {
		root = remove(value, root);
	}

	/**
	 * 在某个节点下删除元素
	 *
	 * @param value
	 *            元素值
	 * @param node
	 *            父节点
	 * @return 删除元素的节点
	 */
	private BinaryNode<AnyType> remove(AnyType value, BinaryNode<AnyType> node) {
		if (node == null) {
			return node;
		}
		int compareResult = value.compareTo(node.element);
		if (compareResult < 0) {
			node.left = remove(value, node.left);
		} else if (compareResult > 0) {
			node.right = remove(value, node.right);
		} else if (node.left != null && node.right != null) {
			node.element = findMin(node.right).element;
			node.right = remove(node.element, node.right);
		} else {
			node = (node.left != null) ? node.left : node.right;
		}
		return node;
	}

	/**
	 * 遍历输出树
	 */
	public void printTree() {
		if (isEmpty()) {
			System.out.println("Empty tree");
		} else {
			printTree(root);
		}
	}

	/**
	 * 先序遍历输出某节点下元素
	 *
	 * @param node
	 *            节点
	 */
	private void printTree(BinaryNode<AnyType> node) {
		if (node != null) {
			printTree(node.left);
			System.out.print(node.element + " ");
			printTree(node.right);
		}
	}

	public static void main(String[] args) {
		BinarySearchTree<Integer> tree = new BinarySearchTree<Integer>();
		tree.insert(8);
		tree.insert(6);
		tree.insert(2);
		tree.insert(4);
		tree.insert(1);
		tree.insert(3);
		tree.printTree();
		tree.remove(2);
		tree.remove(6);
		tree.insert(5);
		tree.insert(7);
		System.out.println("\n------------");
		tree.printTree();
	}
}

执行结果:

1 2 3 4 6 8

------------

1 3 4 5 7 8

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-12-09 08:55:05

数据结构(Java语言)——BinarySearchTree简单实现的相关文章

二、Java语言的简单认识及Hello World示例

1. Java语言的简单认识 (1) Java有三个版本: a. JAVA SE (以前称J2SE):Standard Environment 标准版本: b. JAVA EE (以前称J2EE):Enterprise Environment 企业版: c. JAVA ME (以前称J2ME):Eicro Environment 微型版; (2) Java的安装目录 在前一讲中,提到安装目录中有两个文件夹,分别是jdk1.7.0_45和jre7.在"jdk1.7.0_45"文件夹的bi

java语言实现简单的洗牌,发牌

java学习过程中,老师让写了个简单的斗地主洗牌发牌的程序,一下就是程序代码: package com.java.lei.homework; import java.util.Arrays; import java.util.Random; public class PokerGame { //1.创建数组,用以存储扑克牌 static String[] pokers = new String[54]; public static void main(String[] args) { //2.创

数据结构(java语言描述)顺序栈的使用(两个大数相加)

利用http://www.cnblogs.com/xleer/p/5289661.html中对顺序栈以及栈的进本方法的定义,实现超过整数上限的两个数的加法计算. 算法: package stack;/********************************************************************** * @author sch ********利用栈,计算两个大数的和.大数的值超过int存储的范围******************************

java语言实现简单接口工具--粗简版

2016注定是变化的一年,忙碌.网红.项目融资失败,现在有点时间整整帖子~~ 目标: 提高工作效率与质量,能支持平台全量接口回归测试与迭代测试也要满足单一接口联调测试. 使用人员: 测试,开发 工具包目录: 使用: 1.填写测试案例 2.修改执行配置文件 3.执行jar类 工具进阶: 粗简版 :实现加密解密封装,满足迭代接口自定义参数测试工作: 简单版:实现接口返回值校验:满足平台全量接口回归校验检查,生成测试报告: demo公开版:实现web界面自定义参数设置.测试计划设置.测试案例维护,测试

数据结构(java语言描述)链栈的定义

1.定义栈接口 package stack;public interface Istack {    public void clear();    public boolean isEmpty();    public int length();    public Object peek();    public void push(Object x) throws Exception;    public Object pop();} 2.定义Node结点 package stack; i

数据结构(java语言描述)递归实现——汉诺塔问题

1.汉诺塔问题描述 N阶汉诺塔:假设有3个分别命名为x,y,z的三个塔座,在x上有n个盘子,直径大小不同,有小到大按标号1,2,3...n排列,要借助y将n个盘子转移到z上,期间不能让小盘子压在大盘子上.规则: 每次至移动一个盘子: 盘子可以插在x,y,z任意一个塔座上: 任何时候都不能将大盘压在小盘上. 2.解题思路 当n=1时,直接把盘子由x——>z; 当n>1时,需利用y,首先将(n-1)个盘子由x——>y,把第n个实现x——>z,然后把问题转换为实现(n-1)个盘子由y——

数据结构(java语言描述)哈夫曼编码

原理:哈夫曼编码是根据将已给出的权值作为叶子结点,生成一颗哈夫曼树,然后使得权重最小. 首先生成已给权重的所有的叶子结点,然后取所有节点中最小和次小的结点作为左右孩子生成一个哈夫曼树,计算出父节点的权重放入给出的权重森林中,并把之前的最小和次小的结点从森林中删除,再在种种森林中找最小和次小的结点生成权重树....直到最终只剩下一个树为止. 哈夫曼树的结点用如下结点表示: (有权重,左右孩子,父节点,然后设置一个标识符标志结点是否已经放入哈夫曼树) package tree;/**********

JAVA语言学校的危险性

Java语言学校的危险性(译文) 作者: 阮一峰 日期: 2008年12月 7日 下面的文章是More Joel on Software一书的第8篇. 我觉得翻译难度很大,整整两个工作日,每天8小时以上,才译出了5000字.除了Joel大量使用俚语,另一个原因是原文涉及"编程原理",好多东西我根本不懂.希望懂的朋友帮我看看,译文有没有错误,包括我写的注解. ==================== 作者:Joel Spolsky 译者:阮一峰 原文: http://www.joelon

java语言的特性及应用

java语言定义: Java是一种可以撰写跨平台应用程序的面向对象的程序设计语言. Java 技术具有卓越的通用性.高效性.平台移植性和安全性,广泛应用于PC.数据中心.游戏控制台.科学超级计算机.移动电话和互联网,同时拥有全球最大的开发者专业社群. 组成: Java由四方面组成:●Java编程语言,即语法.●Java文件格式,即各种文件夹.文件的后缀.●Java虚拟机(JVM),即处理*.class文件的解释器.●Java应用程序接口(Java API). Java分为三个体系,分别为Java

java语言具备的11大特点

中软国际武汉java培训专家介绍java语言具备的11大特点. 1.Java语言是简单的 Java 语言的语法与C语言和C++语言很接近,使得大多数程序员很容易学习和使用Java.另一方面,Java丢弃了C++中很少使用的.很难理解的.令人迷惑 的那些特性,如操作符重载.多继承.自动的强制类型转换.特别地,Java语言不使用指针,并提供了自动的废料收集,使得程序员不必为内存管理而担忧. 2.Java语言是一个面向对象的 Java 语言提供类.接口和继承等原语,为了简单起见,只支持类之间的单继承,