您的位置:首页 > 编程语言 > Java开发

Java实现二叉搜索树

2015-11-23 17:20 465 查看

前言

在做算法导论第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(); //中序遍历树

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  数据结构