AVL树的Java实现(递归方法)

       AVL树是一种自平衡的二叉查找树。首先它是一种二叉查找树,满足任意一个节点(叶子节点除外)的值大于它左子树上任意一个节点,且小于它右子树上任意一个节点。因为二叉查找树的深度可能为O(N),这样的效率较低,因此衍生出了AVL树,它具有自平衡的效果,能保持树的深度为O(logN)。AVL树满足:任意一个节点它的左子树的高度和右子树的高度差不超过1。(假设叶子节点的高度为0,null节点的高度为-1)

      基于上述的理论完成程序的编写,既然要保存每个节点的高度,Node节点就需要一个int类型的height变量。自己完成的是采用递归的方法,以后有时间完成非递归方法的实现。上代码:

public class TreeTest
{
	public static void main(String[] args)
	{
		AVLTree<Integer> st=new AVLTree<Integer>();
		st.insert(15);
		st.insert(7);
		st.insert(5);
		st.insert(37);
		st.insert(70);
		System.out.println("插入节点:"+st);
		st.remove(7);
		st.remove(15);
		System.out.println("删除节点:"+st);
	}
	
}

//AVL树:每个节点的左子树和右子树的高度差最多为1
class AVLTree<T extends Comparable<T>>
{
	private Node<T> root=null;
	
	public AVLTree()
	{	
	}
	public void insert(T t)
	{
		root=insert(t,root);
	}
	public void remove(T t)
	{
		root=remove(t,root);	
	}
	public T findMax()
	{
		if(root==null)     //如果还没有元素则返回空
			return null;
		return findMax(root).element;
	}
	public T findMin()
	{
		if(root==null)		//如果还没有元素则返回空
			return null;
		return findMin(root).element;
	}
	//先序遍历
	public void printFirst()
	{
		System.out.print("先序遍历:");
		printFirst(root);
		System.out.print("\n");
	}
	private void printFirst(Node<T> node)
	{
		if(node!=null)
		{
			System.out.print(node.element+" ");
			printFirst(node.left);
			printFirst(node.right);
		}
	}
	//中序遍历
	public void printTree()
	{
		System.out.print("中序遍历:");
		printTree(root);
		System.out.print("\n");
	}
	private void printTree(Node<T> node)
	{
		if(node!=null)
		{
			printTree(node.left);
			System.out.print(node.element+" ");
			printTree(node.right);
		}
	}
	//插入分为4总情况,分为两组,这两组镜像对称。返回之前要进行node的高度赋值
	private Node<T> insert(T t,Node<T> node)
	{
		if(node==null)
			return new Node<T>(t,null,null);
		int i=t.compareTo(node.element);
		if(i>0)
		{
			node.right=insert(t,node.right);
			
			int cha=height(node.left)-height(node.right);
			if(cha>1 | cha<-1)
			{
				if(t.compareTo(node.right.element)>0)
					node=singleRightChild(node);
				else
					node=doubleRightChild(node);
			}
		}
		else
		{
			if(i<0)
			{
				node.left=insert(t,node.left);
				int cha=height(node.left)-height(node.right);
				if(cha>1 | cha<-1)
				{
					if(t.compareTo(node.left.element)<0)
						node=singleLeftChild(node);
					else
						node=doubleLeftChild(node);
				}
			}
		}
		node.height=Math.max(height(node.left),height(node.right))+1;
		return node;
	}
//删除节点方法:递归删除(三种情况),再判断node节点左右子节点的高度差,|差|>1则进行旋转平衡,高度赋值
	private Node<T> remove(T t,Node<T> node)
	{
		if(node==null) 	
			return null;
		int i=t.compareTo(node.element);
		if(i==0)
		{
			if(node.right!=null && node.left!=null)
			{
				node.element=findMin(node.right).element;
				node.right=remove(node.element,node.right);
			}
			else
				node=(node.right==null)?node.left:node.right;
		}
		else if(i>0)
			node.right=remove(t,node.right);
		else
			node.left=remove(t,node.left);
		if(node!=null)	   							//如果该节点不为空,则进行平衡的判别处理和高度的赋值
		{
			if(height(node.right)-height(node.left)>1)   	//进行右旋转
			{
				if(height(node.right.right)>=height(node.right.left))   //进行单旋转
					node=singleRightChild(node);
				else										//进行双旋转
					node=doubleRightChild(node);
			}
			else if(height(node.left)-height(node.right)>1)	//进行左旋转
			{
				if(height(node.left.left)>=height(node.left.right))   //进行单旋转
					node=singleLeftChild(node);
				else										//进行双旋转
					node=doubleLeftChild(node);
			}
			node.height=Math.max(height(node.right),height(node.left))+1;
		}
		return node;
	}
	private Node<T> singleRightChild(Node<T> node)
	{
		Node<T> n=node.right;
		node.right=n.left;
		n.left=node;
		node.height=Math.max(height(node.left),height(node.right))+1;
		n.height=Math.max(height(n.right),height(n.left))+1;
		return n;
	}
	private Node<T> singleLeftChild(Node<T> node)
	{
		Node<T> n=node.left;
		node.left=n.right;
		n.right=node;
		node.height=Math.max(height(node.left),height(node.right))+1;
		n.height=Math.max(height(n.right),height(n.left))+1;
		return n;
	}
	//一次双旋转=两次单旋转
	private Node<T> doubleRightChild(Node<T> node)
	{
		node.right=singleLeftChild(node.right);
		return singleRightChild(node);
	}
	private Node<T> doubleLeftChild(Node<T> node)
	{
		node.left=singleRightChild(node.left);
		return singleLeftChild(node);
	}
	//返回节点的高度,空节点为-1。新建节点的高度为0
	private int height(Node<T> node)
	{
		return (node==null)?-1:node.height;
	}
	//返回元素最小的节点
	private Node<T> findMin(Node<T> node)
	{
		if(node==null)
			return null;
		if(node.left==null)
			return node;
		return findMin(node.left);
	}
	//返回元素最大的节点
	private Node<T> findMax(Node<T> node)
	{
		if(node==null)
			return null;
		if(node.right==null)
			return node;
		return findMax(node.right);
	}
	//节点类,包含元素和高度信息
	private static class Node<T>
	{
		private T element;
		private int height;
		private Node<T> left;
		private Node<T> right;
		public Node(T element,Node<T> left,Node<T> right)
		{
			this.element=element;
			this.left=left;
			this.right=right;
			height=0;
		}
	}	
	@Override
	public String toString()
	{
		StringBuilder sb=new StringBuilder();
		sb.append("[");
		sb.append(print(root));
		sb.append("]");
		return sb.toString();
	}
	//递归输出,中序遍历
	private String print(Node<T> node)
	{
		if(node!=null)
		{
			StringBuilder sb=new StringBuilder();
			sb.append(print(node.left));
			if(node.left!=null)
				sb.append(",");
			sb.append(node.element);
			if(node.right!=null)
				sb.append(",");
			sb.append(print(node.right));
			return sb.toString();
		}
		return "";
	}
}
输出结果:

发布了26 篇原创文章 · 获赞 5 · 访问量 2万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章