二叉搜索树的实现

来源:互联网 发布:c语言共用体union例子 编辑:程序博客网 时间:2024/05/29 08:34

二叉搜索树需要满足的条件: 

1. 所有节点最多只能有2个节点(left节点,right节点)

2. 左子树 < 根节点 < 右子树


思路: 在二叉搜索树内部,先定义一个节点对象,除了包含关键字之外,还要包含其左右节点以及父节点

          每个二叉搜索树初始化时先定义一个根节点,插入的时候都从根节点开始插入, 根节点不为空,则比较其大小, 

          小的跟左节点比较,大的跟右节点比较, 直到找到一个符合条件的空节点

          程序中不允许有相等的值插入,如果需要插入相等的值, 可以稍微修改下代码: 把所有相等的都看作是大于, 遇到第一个相等节点时, 直接插入其right节点

           如果right节点已经存在,那么把已经存在的这个节点当做新节点的右节点. 对应的搜索算法也需要改变,在搜索到相等的时候,还要继续搜索下去


搜索二叉树在左右节点均衡时,性能基本接近二分搜索,但是二叉搜索树性能是否均衡严重依赖其节点加入顺序

如果按升序或者降序来逐个添加节点,那么得到的将是一个只有右子树 或者 只有左子树的二叉树, 完全是一个线性结构了

这个缺点可以通过平衡二叉树(深度差不超过1),或者红黑树(深度差不能超出1倍)来改进(jdk中多使用红黑树)

基本原理就是在插入节点导致不平衡后,需要通过旋转不平衡的节点,来保持平衡


package com.xp.test;/** * 二叉搜索树 * @author admin * * @param <T> */public class MyBinaryTree<T extends Comparable<T>> {//定义一个跟节点,初始化时为空private TreeNode root = null;public MyBinaryTree() {}/** * 新增对象 * @param i */public void add(T i) {TreeNode node = new TreeNode(i);//加入第一个节点时,直接将root节点指向新增的节点if(root == null) {root = node;} else {//递归新增add(node,root);}}/** * 递归新增节点 *  * @param node1 * @param node2 */private void add(TreeNode node1, TreeNode node2) {if(node2 == null) {node2 = node1;} else {//等于比较节点,抛出异常if(node1.value.compareTo(node2.value) == 0 ) {//相同元素不允许插入throw  new RuntimeException(" 重复元素! ");} else if(node1.value.compareTo(node2.value) > 0 ){//大于比较的节点,那么应该插入right节点if(node2.right != null) {//right不为空的话,应该递归搜索右子树add(node1,node2.right);} else {//right节点为空,那么将其作为比较节点的right节点并且parent指向比较节点node2.right = node1;node1.parent = node2;}} else if(node1.value .compareTo(node2.value) < 0 ) {if(node2.left != null) {add(node1,node2.left);} else {node2.left = node1;node1.parent = node2;}}}}/** * 获取最小值 * @return */public T getMin() {if(root == null) {throw new RuntimeException(" 元素为空无法获取最小值! ");} else {return getLeft(root).value;}}/** * 递归搜索左子树 * @param node * @return */private TreeNode getLeft(TreeNode node) {if(node.left == null) {return node;} else {return getLeft(node.left);}}/** * 获取最大值 * @return */public T getMax() {if(root == null) {throw new RuntimeException(" 元素为空无法获取最大值! ");} else {return getRight(root).value;}}/** * 递归搜索右子树 * @param node * @return */private TreeNode getRight(TreeNode node) {if(node.right == null) {return node;} else {return getRight(node.right);}}/** * 从根节点开始,进行中序遍历 */public void iteratorLNR() {if(root != null) {iteratorLNR(root);}}/** * 递归遍历 * @param node */private void iteratorLNR(TreeNode node) {if(node != null) {iteratorLNR(node.left);System.out.println(node.value);iteratorLNR(node.right);}}/** * 从根节点开始搜索指定的对象 * @param t * @return */public T search(T t) {return search(root,t);}/** * 对每个节点递归搜索指定的对象 * @param node * @param t * @return */private T search(TreeNode node, T t) {if(node == null) {return null;} else {int i = t.compareTo(node.value);if(i == 0) {return node.value;} else if(i > 0) {return search(node.right,t);} else if(i < 0) {return search(node.left,t);}}return null;}/** * 内部节点,除了包含关键字之外,还包含了这个节点的left,right,parent节点的指向 * @author admin * */private class TreeNode {private T value;private TreeNode left;private TreeNode right;private TreeNode parent;public TreeNode(T value) {this.value = value;}}public static void main(String[] args) {MyBinaryTree<Integer> t = new MyBinaryTree<Integer>();t.add(50);t.add(1);t.add(2);t.add(5);t.add(3);t.add(-50);t.add(-1);t.add(-100);t.add(100);t.add(1000);t.add(99);t.add(10000);System.out.println("min:" + t.getMin());System.out.println("max:" + t.getMax());t.iteratorLNR();System.out.println("search value = 2 :" + t.search(2));System.out.println("search value = 4 :" + t.search(4));System.out.println("search value = -3 :" + t.search(-3));}}


执行结果:

min:-100
max:10000
-100,-50,-1,1,2,3,5,50,99,100,1000,10000,
search value = 2 :2
search value = 4 :null
search value = -3 :null

0 0
原创粉丝点击