java实现二分搜索树

二分搜索树的优势

查找元素、插入元素、删除元素的时间复杂度都是O(logn)。还可以方便的回答很多数据之间关系的问题:min,max,floor,ceil,rank,select

 

例如rank,求key=45在所有节点中排名第几?

答:可以通过给Node增加一个属性,记录以当前节点为根节点的二叉树的所有节点数(包括根节点),通过它可以方便得知排名

结构

二分搜索树是一棵二叉树,每个节点的键值小于右孩子大于左孩子,以左右孩子为根的子树仍为二分搜索树。

节点类

public class Node {
	private int key;
	private String value;
	private Node LeftChild;
	private Node RightChild;
	
	public Node(int key, String value) {
		this.key = key;
		this.value = value;
		LeftChild = null;
		RightChild = null;
	}
	public Node(Node node) {
		this.key = node.getKey();
		this.value = node.getValue();
		LeftChild = node.getLeftChild();
		RightChild = node.getRightChild();
	}
	public int getKey() {
		return key;
	}
	public void setKey(int key) {
		this.key = key;
	}
	public String getValue() {
		return value;
	}
	public void setValue(String value) {
		this.value = value;
	}
	public Node getLeftChild() {
		return LeftChild;
	}
	public void setLeftChild(Node leftChild) {
		LeftChild = leftChild;
	}
	public Node getRightChild() {
		return RightChild;
	}
	public void setRightChild(Node rightChild) {
		RightChild = rightChild;
	}
	
}

二分搜索树类

public class Two_SearchTree {
	private Node RootNode;       //根节点
	private int count;          //节点数
	
	public Two_SearchTree() {
		RootNode = null;
		this.count = 0;
	}
	public int size(){
		return count;
	}
	public boolean isEmpty(){
		return count==0;
	}
	public boolean contain(int key){
		return contain(RootNode,key);
	}
	public void insert(int key,String value){
		RootNode=insert(RootNode,key,value);
	}
	public String search(int key){
		return search(RootNode,key);
	}
	public void preOrder(){
		preOrder(RootNode);
	}
	public void inOrder(){
		inOrder(RootNode);
	}
	public void postOrder(){
		postOrder(RootNode);
	}
	//层序遍历
	public void levelOrder(){
		Queue queue=new LinkedList();    //通过LinkedList来实现队列
		queue.offer(RootNode);     //头元素入队
		while(!queue.isEmpty()){
			Node node=queue.peek();     
			queue.poll();      //头元素出队列
			System.out.println(node.getKey());
			if(node.getLeftChild()!=null){   //左孩子不为空,则左孩子入队
				queue.offer(node.getLeftChild());
			}
			if(node.getRightChild()!=null){  //右孩子不为空,则右孩子入队
				queue.offer(node.getRightChild());
			}
		}
	}
	//寻找最小的键值
	public int minimum(){
		assert(count!=0);
		Node minNode=minimum(RootNode);
		return minNode.getKey();
	}
	//返回最大的键值
	public int maximum(){
		assert(count!=0);
		Node maxNode=maximum(RootNode);
		return maxNode.getKey();
	}
	//删除最小键值的节点
	public void removeMin(){
		if(RootNode!=null){
			RootNode=removeMin(RootNode);
		}
	}
	//删除最大键值的节点
	public void removeMax(){
		if(RootNode!=null){
			RootNode=removeMax(RootNode);
		}
	}
	//删除键值为key的节点
	public void remove(int key){
		RootNode=remove(RootNode,key);
	}
	
	
	
	//向以RootNode为根的二叉搜索树中插入节点(key,value)
	//返回插入新节点后的二叉搜索树的根
	private Node insert(Node RootNode,int key,String value){
		if(RootNode==null){         //这是没有左孩子或右孩子的情况
			count++;
			return new Node(key,value);
		}
		if(key==RootNode.getKey()){
			RootNode.setValue(value);
		}else if(keyRootNode.getKey()
			RootNode.setRightChild(insert(RootNode.getRightChild(),key,value));
		}
		return RootNode;
		
	}
	//查看以RootNode为根的二叉搜索树中是否包含键为key的节点
	private boolean contain(Node RootNode,int key){
		if(RootNode==null){      
			return false;
		}
		if(key==RootNode.getKey()){
			return true;
		}else if(keyleft!=null&&node->right!=null         删除左右都有孩子的节点
			Node successor=new Node(minimum(node.getRightChild())); //代替被删除节点的节点
			count++;
			successor.setRightChild(removeMin(node.getRightChild()));
			successor.setLeftChild(node.getLeftChild());
			count--;
			return successor;
		}else if(key

二分搜索树的局限性

当将一组数据以近乎有序的顺序插入空二分搜索树中时,几乎每一个节点都是父节点的右孩子,二分搜索树近乎退化成了一个链表,相关算法时间复杂度都退化成了O(N)。因此有了平衡二叉树,不会退化成链表,如:红黑树等。

其他平衡二叉树还有:2-3树,AVL树,Splay树

还有平衡二叉树和堆的结合:Treap

还有个trie数据结构也很有意思

 

你可能感兴趣的:(数据结构与算法,二叉树,搜索,结构,java,博客)