Java实现二叉排序树

定义:

二叉排序树或者是一棵空树,或者是具有下列性质的 二叉树
(1)若左子树不空,则左子树上所有结点的值均小于它的 根结点的值;
(2)若右子树不空,则右子树上所有结点的值均大于或 等于它的根结点的值;
(3)左、右子树也分别为二叉排序树;
(4)没有键值相等的节点。

说明:

可实现:构造树,插入,查找,删除.

通过模式的选择,可以插入值相等的点.但是不建议使用.


代码:

节点类Node:

package glut.bean;
public class Node {
	Node parent;
	Node leftChild;
	Node rightChild;
	int index;
	Number value;
	boolean isLeftChild;

	public Node() {
		// TODO Auto-generated constructor stub
	}

	public Node(Node parent, Node leftChild, Node rightChild, Number value) {
		this.parent = parent;
		this.leftChild = leftChild;
		this.rightChild = rightChild;
		this.value = value;
	}
}

排序树类SortedTree:

package glut.bean;

import java.util.ArrayList;
import java.util.List;

public class SortedTree {
	private List<Number> arr;
	private Node root;
	private boolean allowTheSameNumber = false;

	/**
	 * 不能使用默认构造器
	 */
	private SortedTree() {
		// TODO Auto-generated constructor stub

	}

	/**
	 * 必须给定一个List,且list不能为空
	 * 
	 * @param arr
	 */
	public SortedTree(List<Number> arr) {
		this.arr = arr;
		if (!arr.isEmpty()) {
			root = new Node();
			root.parent = null;
			root.leftChild = null;
			root.rightChild = null;

			createSortedTree();
		} else {
			try {
				throw new Exception("Array is empty");
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}

	/**
	 * 必须给定一个List,且list不能为空
	 * 
	 * @param arr
	 * @param allowTheSameNumber
	 *            是否允许重复数字(建议false).true:allow ;false: not allow
	 */
	public SortedTree(List<Number> arr, boolean allowTheSameNumber) {
		this.arr = arr;
		this.allowTheSameNumber = allowTheSameNumber;
		if (!arr.isEmpty()) {
			root = new Node();
			root.parent = null;
			root.leftChild = null;
			root.rightChild = null;

			createSortedTree();
		} else {
			try {
				throw new Exception("Array is empty");
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}

	/**
	 * 以下参数都是通过createSortedTree方法的for循环获取
	 * 
	 * @param value
	 * @param curNode
	 * @param index
	 */
	private void build(Number value, Node curNode, int index) {
		// 向左转
		if (value.doubleValue() < curNode.value.doubleValue()) {
			// 如果没有左节点,就创建
			if (curNode.leftChild == null) {
				curNode.leftChild = createNewNode(value, curNode, index, true);
				return;
			}
			// 有就继续遍历
			build(value, curNode.leftChild, index);
			// 向右转
		} else if (value.doubleValue() > curNode.value.doubleValue()) {
			// 如果没有右节点,就创建
			if (curNode.rightChild == null) {
				curNode.rightChild = createNewNode(value, curNode, index, false);
				return;
			}
			// 有就继续遍历
			build(value, curNode.rightChild, index);
			// 相同的值
		} else {
			if (!allowTheSameNumber) {
				try {
					throw new Exception("has the same number");
				} catch (Exception e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				// 如果允许相同的值,则将它放在右子树
			} else {
				// 如果没有右节点,就创建
				if (curNode.rightChild == null) {
					curNode.rightChild = createNewNode(value, curNode, index,
							false);
					return;
				}
				// 有就继续遍历
				build(value, curNode.rightChild, index);
			}
		}
	}

	/**
	 * 
	 * @param value
	 * @param curNode
	 *            当前节点
	 * @param index
	 *            下标
	 * @param isLeftChild
	 *            是否为左节点
	 * @return 新创建的节点
	 */
	private Node createNewNode(Number value, Node curNode, int index,
			boolean isLeftChild) {
		Node newNode = new Node();
		newNode.value = value;
		// 将当前节点作为新建节点的双亲节点
		newNode.parent = curNode;
		newNode.index = index;
		newNode.isLeftChild = isLeftChild;
		return newNode;
	}

	private void createSortedTree() {
		// 默认将arr中第一个元素放到根
		root.value = arr.get(0);
		root.index = 0;
		for (int i = 1; i < arr.size(); i++) {
			build(arr.get(i), root, i);
		}
	}

	/**
	 * 
	 * @param value
	 *            给定的值
	 * @return 给定的值在arr中的下标
	 */
	public int indexOf(Number value) {
		Node targetNode = find(value, root);
		return targetNode == null ? -1 : targetNode.index;
	}

	/**
	 * 
	 * @param value
	 *            给定的值
	 * @return 给定的值的节点
	 */
	public Node get(Number value) {
		return find(value, root);
	}

	/**
	 * 
	 * @param value查找的值
	 * @param curNode
	 *            第一个查找的节点(默认为根节点)
	 * @return如果存在指定值的节点,返回.否则返回null
	 */
	private Node find(Number value, Node curNode) {
		if (curNode != null) {
			if (value.doubleValue() < curNode.value.doubleValue()) {
				return find(value, curNode.leftChild);
			} else if (value.doubleValue() > curNode.value.doubleValue()) {
				return find(value, curNode.rightChild);
			} else {
				return curNode;
			}
		} else {
			return null;
		}
	}

	/**
	 * 
	 * 
	 * @return 排序后的数组(重复的数字只显示一次)
	 */
	public List<Number> getSortedArray() {
		// newArr用于存放升序排列后的数组
		List<Number> newArr = new ArrayList<Number>();
		midTraversal(root, newArr);
		return newArr;
	}

	// 中序遍历二叉排序树会得到升序的数组
	private void midTraversal(Node curNode, List<Number> newArr) {
		// TODO Auto-generated method stub
		// 如果没有左子树,意味着遍历到头了
		if (curNode.leftChild == null) {
			// 直接把该店的值添加到数组里
			newArr.add(curNode.value);
			// 如果有左子树,继续遍历
		} else {
			midTraversal(curNode.leftChild, newArr);
			// 并且在遍历完后将该节点的值添加到数组里
			newArr.add(curNode.value);
		}
		// 最后遍历右子树
		if (curNode.rightChild != null) {
			midTraversal(curNode.rightChild, newArr);
		}
	}

	/**
	 * 
	 * @param value
	 *            要添加的值
	 */
	public void insert(Number value) {
		// 先将值添加到list里
		arr.add(value);
		// 进行插入操作
		build(value, root, arr.size() - 1);
	}

	/**
	 * 删除给定的值的第一次出现的节点
	 * 
	 * @param value
	 *            要删除的值
	 */
	public void delete(Number value) {
		// 先看看有没有这个节点
		Node targetNode = find(value, root);
		// 如果没有这个节点,抛出找不到的异常
		if (targetNode == null) {
			try {
				throw new Exception("specified value not found");
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		// 如果有这个节点
		// 当该节点拥有2个子节点
		if (targetNode.leftChild != null && targetNode.rightChild != null) {
			// 可以从目标节点的左子树中找到最大的值,来替换目标节点(也可以通过右子数)
			// maxNodeOfLeft: the max value node of the left tree of the target
			Node maxNodeOfLeft = findLeftMaxNode(targetNode);
			// 将左子树中最大的节点的值和下标放到目标节点中
			targetNode.value = maxNodeOfLeft.value;
			targetNode.index = maxNodeOfLeft.index;
			// leftChildOfMaxNode:the left child of the max node
			Node leftChildOfMaxNode = maxNodeOfLeft.leftChild;
			Node parent = maxNodeOfLeft.parent;

			if (leftChildOfMaxNode != null) {
				// 进行节点连接操作
				leftChildOfMaxNode.parent = parent;
				connected(maxNodeOfLeft, leftChildOfMaxNode, parent);
			} else {
				// 进行节点连接操作
				connected(maxNodeOfLeft, null, parent);
			}
			maxNodeOfLeft = null;
			// 如果无子节点
		} else if (targetNode.leftChild == null
				&& targetNode.rightChild == null) {
			// 进行节点连接操作
			Node parent = targetNode.parent;
			connected(targetNode, null, parent);
			targetNode = null;
			// 如果只有一个子节点
		} else {
			Node targetNodeLeftChild = targetNode.leftChild;
			Node parent = targetNode.parent;
			// 如果目标节点没有左子树
			if (targetNodeLeftChild == null) {
				// 那它肯定有右子树
				Node targetNodeRightChild = targetNode.rightChild;
				// 进行节点连接操作
				targetNodeRightChild.parent = parent;
				connected(targetNode, targetNodeRightChild, parent);
			} else {
				// 进行节点连接操作
				targetNodeLeftChild.parent = parent;
				connected(targetNode, targetNodeLeftChild, parent);
			}
		}
	}

	/**
	 * 
	 * @param childNode
	 *            子节点
	 * @param childOfChildNode
	 *            子节点的子节点
	 * @param parentNode
	 *            子节点的双亲节点
	 */
	private void connected(Node childNode, Node childOfChildNode,
			Node parentNode) {
		if (childNode.isLeftChild) {
			parentNode.leftChild = childOfChildNode;
		} else {
			parentNode.rightChild = childOfChildNode;
		}
	}

	/**
	 * 
	 * @param targetNode
	 *            目标节点
	 * @return 返回值是指定节点的左子树中值最大的节点
	 */
	private Node findLeftMaxNode(Node targetNode) {
		Node maxNodeOfLeft = targetNode.leftChild;
		// 一直右下,直到叶子
		while (maxNodeOfLeft.rightChild != null) {
			maxNodeOfLeft = maxNodeOfLeft.rightChild;
		}
		return maxNodeOfLeft;
	}

	public List<Number> getArr() {
		return arr;
	}

	public void setArr(List<Number> arr) {
		this.arr = arr;
	}

}

测试代码:

package glut.test;

import glut.bean.SortedTree;

import java.util.ArrayList;
import java.util.List;

public class MyTest {
	public static void main(String[] args) {

		List<Number> arr = new ArrayList<Number>();

		init(arr);

		SortedTree st = new SortedTree(arr, true);

		st.get(8);

		st.insert(10);

		st.delete(9);
		
		List<Number> array = st.getSortedArray();
		for (Number number : array) {
			System.out.print(number + ",");
		}

	}

	private static void init(List<Number> arr) {
		arr.add(7);
		arr.add(2);
		arr.add(1);
		arr.add(0);
		arr.add(5);
		arr.add(4);
		arr.add(3);
		arr.add(6);
		arr.add(9);
		arr.add(8);
	}

}



项目源码SVN地址:http://code.taobao.org/p/sortedTreeDemo/src/

CSDN下载:http://download.csdn.net/detail/lc0817/9074469

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值