二叉搜索树的实现

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

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值