Java创建AVL树

AVL树是带有平衡条件的二叉查找树,其查找和删除的时间复杂度为logn,是对二叉查找树的改进,我们将节点的左子树和右子树深度之差称为平衡因子(BF),其中的每一个节点的平衡因子的绝对值不大于1。

距离插入节点最近的,并且平衡因子绝对值大于1的节点为根的子树,称为最小不平衡子树。

要实现AVL树,就必须保证在插入的时候消除不平衡的子树,即通过某种方式,使每次插入一个节点,都是平衡的BST树,下面我们讨论一下插入的时候四种情况:

1:对左孩子的左子树进行一次插入;

2:对左孩子的右子树进行一次插入;

3:对右孩子的左子树进行一次插入;

4:对右孩子的右子树进行一次插入;

其中情况1和情况4是关于镜像对称的,情况2和情况3是关于镜像对称的,

由于图片原因,我就上了几张不好看的图片,其中x,y,z和A,B,C,D为对应的节点的孩子,我直接对四种情况进行讲解:

情况1:假设节点k1,k1的左孩子k2,

单右旋转:对k1节点的左孩子k2的左子树进行插入,这样使得k1的BF为2,此时最小不平衡子树是以k1为根节点的子树,因此对其进行右旋转操作,使得新子树的根节点为原节点的左孩子即k2,k2的右孩子为k1,k1的左孩子为原子树中k2的右孩子;

情况2:假设节点k1,k1的左孩子k3,k3的右孩子k2,

双左旋转:对以k2为根节点的子树进行插入操作,这时最小的不平衡子树是以k1为根节点的子树,但是单纯的左旋转不能解决问题,这和情况1有所区别,其原因在于K1的BF为2,而K3的BF为-1,两者的符号不一致,导致了不能只是进行一次旋转,所以分为两次旋转:

1:先对以K3为根节点的子树进行左旋转,

2:再对以K1为根节点的子树进行右旋转,

得到图中所示的结果,此时K2左子树B是K3右子树,K2右子树C是K1左子树,K2左孩子为K3,K2右孩子为K1;

情况3:

假设节点k1,k1的右孩子k3,k3的左孩子k2,

双右旋转:对以k2为根节点的子树进行插入操作,这时最小的不平衡子树是以k1为根节点的子树,但是单纯的左旋转不能解决问题,这和情况1有所区别,其原因在于K1的BF为-2,而K3的BF为1,两者的符号不一致,导致了不能只是进行一次旋转,所以分为两次旋转:

1:先对以K3为根节点的子树进行右旋转,

2:再对以K1为根节点的子树进行左旋转,

得到图中所示的结果,此时K2右子树C是K3左子树,K2左子树B是K1右子树,K2左孩子为K1,K2右孩子为K3;

情况1:假设节点k1,k1的左孩子k2,

单右旋转:对k1节点的左孩子k2的左子树进行插入,这样使得k1的BF为2,此时最小不平衡子树是以k1为根节点的子树,因此对其进行右旋转操作,使得新子树的根节点为原节点的左孩子即k2,k2的右孩子为k1,k1的左孩子为k2的右孩子;

情况4:假设节点k1,k1的右孩子k2,

单右旋转:对k1节点的右孩子k2的左子树进行插入,这样使得k1的BF为-2,此时最小不平衡子树是以k1为根节点的子树,因此对其进行左旋转操作,使得新子树的根节点为原节点的右孩子即k2,k2的左孩子为k1,k1的左孩子为原子树中k2的左孩子;

下面是Java代码实现:

package data_structure;

@SuppressWarnings("rawtypes")
public class AVL<AnyType extends Comparable> {

	private AVLNode root;

	 //定义范型Anytype的大小比较方法

	@SuppressWarnings("unused")
	/*private  class Anytype implements Comparable<AnyType>{

		private AnyType x;
		@Override
		public int compareTo(AnyType o) {
			String s=x.toString();
			String target=o.toString();
			return s.compareTo(target);
		}

	}*/
	private  class AVLNode<AnyType>{
		AnyType element;
		AVLNode<AnyType> left;
		AVLNode<AnyType> right;
		int height;

		@SuppressWarnings("unused")
		public AVLNode(AnyType data){
			this(data,null,null);
		}

		public AVLNode(AnyType data,AVLNode<AnyType> lc,AVLNode<AnyType> rc){
			element=data;
			left=lc;
			right=rc;
			height=0;
		}

	}

	private int getHeight(AVLNode<AnyType> t){
		return t==null?-1:t.height;
	}

	@SuppressWarnings("unchecked")
	private int compare(AnyType x,AnyType y){
		if(x.compareTo(y)>0)
			return 1;
		else if(x.compareTo(y)<0)
			return -1;
		return 0;
	}
	//单旋转左旋转
	private AVLNode<AnyType> rotateWithLeftChild(AVLNode<AnyType> k1){
		AVLNode<AnyType> k2=k1.right;
		k1.right=k2.left;
		k2.left=k1;
		k2.height=Math.max(getHeight(k2.left), getHeight(k2.right))+1;
		k1.height=Math.max(getHeight(k1.left), getHeight(k1.right))+1;
		return k2;
	}
	//单旋转右旋转
	private AVLNode<AnyType> rotateWithRightChild(AVLNode<AnyType> k1){
		AVLNode<AnyType> k2=k1.left;
		k1.left=k2.right;
		k2.right=k1;
		k2.height=Math.max(getHeight(k2.left), getHeight(k2.right))+1;
		k1.height=Math.max(getHeight(k1.left), getHeight(k1.right))+1;
		return k2;
	}
	//双旋转左旋转,分为两个步骤:先右旋转以右孩子为根的子树,然后左旋转k1
	private AVLNode<AnyType> doubleWithLeftChild(AVLNode<AnyType> k1){
		k1.right=rotateWithRightChild(k1.right);//千万要注意k1.right不要掉了,不然k2丢了
		return rotateWithLeftChild(k1);
	}
	//双旋转右旋转,分为两个步骤:先左旋转以右孩子为根的子树,然后右旋转k1
	private AVLNode<AnyType> doubleWithRightChild(AVLNode<AnyType> k1){
		k1.left=rotateWithLeftChild(k1.left);//千万要注意k1.left不要掉了,不然k2丢了
		return rotateWithRightChild(k1);
	}
	//使用递归的方式插入,每次返回插入子树根节点,x为待插入元素
	@SuppressWarnings("unchecked")
	private AVLNode<AnyType> insert(AnyType x,AVLNode<AnyType> t){
		System.out.print(x+" ");
		if(t==null)
			return new AVLNode(x,null,null);
		int result=compare(x, t.element);
		if(result<0){
			t.left=insert(x, t.left);
			if(getHeight(t.left)-getHeight(t.right)==2)
				if(compare(x, t.left.element)<0)
					t=rotateWithRightChild(t);
			    if(compare(x, t.left.element)>0)
			    	t=doubleWithRightChild(t);
		}
		if(result>0){
			t.right=insert(x, t.right);
			if(getHeight(t.right)-getHeight(t.left)==2)
				if(compare(x,t.right.element)>0)
					t=rotateWithLeftChild(t);
			    if(compare(x,t.right.element)<0)
			    	t=doubleWithLeftChild(t);
		}
		t.height=Math.max(getHeight(t.left), getHeight(t.right))+1;
		return t;
	}

	@SuppressWarnings("unchecked")
	private void createAVl(AnyType [] data){
		for(AnyType a:data)
			root=insert(a, root);
	}

	private void printTree(AVLNode root){
		if(root==null)
			return ;
		printTree(root.left);
		System.out.print(root.element+"  ");
		printTree(root.right);
	}

	public static void main(String []args){
		Integer []data={2,6,8,4,12,45,25,14,28};
		AVL<Integer> avl=new AVL<Integer>();
		avl.createAVl(data);
		System.out.println();
		avl.printTree(avl.root);
	}
}
时间: 2024-10-10 23:03:45

Java创建AVL树的相关文章

JAVA数据结构--AVL树的实现

AVL树的定义 在计算机科学中,AVL树是最先发明的自平衡二叉查找树.在AVL树中任何节点的两个子树的高度最大差别为1,所以它也被称为高度平衡树.查找.插入和删除在平均和最坏情况下的时间复杂度都是.增加和删除可能需要通过一次或多次树旋转来重新平衡这个树.AVL树得名于它的发明者G. M. Adelson-Velsky和E. M. Landis,他们在1962年的论文<An algorithm for the organization of information>中发表了它. 节点的平衡因子是

AVL树的创建与旋转

AVL树写的不耐烦了,索性一次性代码贴上... /** 2 * AVL树(C语言): C语言实现的AVL树. 3 * 4 * @author skywang 5 * @date 2013/11/07 6 */ #include <stdio.h> #include <stdlib.h> #define HEIGHT(p) ( (p==NULL) ? -1 : (((Node *)(p))->height) ) #define MAX(a, b) ( (a) > (b)

AVL树(平衡二叉查找树)

首先要说AVL树,我们就必须先说二叉查找树,先介绍二叉查找树的一些特性,然后我们再来说平衡树的一些特性,结合这些特性,然后来介绍AVL树. 一.二叉查找树 1.二叉树查找树的相关特征定义 二叉树查找树,又叫二叉搜索树,是一种有顺序有规律的树结构.它可以有以下几个特征来定义它: (1)首先它是一个二叉树,具备二叉树的所有特性,他可以有左右子节点(左右孩子),可以进行插入,删除,遍历等操作: (2)如果根节点有左子树,则左子树上的所有节点的值均小于根节点上的值,如果根节点有右子树,则有字数上的所有节

[转载]AVL树(一)之 图文解析 和 C语言的实现

概要 本章介绍AVL树.和前面介绍"二叉查找树"的流程一样,本章先对AVL树的理论知识进行简单介绍,然后给出C语言的实现.本篇实现的二叉查找树是C语言版的,后面章节再分别给出C++和Java版本的实现. 建议:若您对"二叉查找树"不熟悉,建议先学完"二叉查找树"再来学习AVL树. 目录 1. AVL树的介绍 2. AVL树的C实现3. AVL树的C实现(完整源码) 4. AVL树的C测试程序 转载请注明出处:http://www.cnblogs.

深度解析(七)AVL树

AVL树(一)之 图文解析 和 C语言的实现 概要 本章介绍AVL树.和前面介绍"二叉查找树"的流程一样,本章先对AVL树的理论知识进行简单介绍,然后给出C语言的实现.本篇实现的二叉查找树是C语言版的,后面章节再分别给出C++和Java版本的实现.建议:若您对"二叉查找树"不熟悉,建议先学完"二叉查找树"再来学习AVL树. 目录 1. AVL树的介绍2. AVL树的C实现3. AVL树的C实现(完整源码)4. AVL树的C测试程序 转载请注明出处

【数据结构】平衡二叉排序树BBST之AVL树

平衡二叉排序树 平衡二叉排序树(Balanced Binary Sort Tree),上一篇博客[数据结构]二叉排序树BST讲了BST,并且在最后我们说BST上的操作不会超过O(h),既然树高这么重要,那么BBST的研究就是为了使得树的深度在可接受的范围内渐近意义下达到O(lgn) n个节点组成的二叉树,其高度为lgn取下限时,这棵树是理想平衡的,满足这样条件的树只有完全二叉树和满二叉树,这样的要求未免太苛刻,并且实际中没有意义. 适度平衡:保证树高在渐近意义上不超过O(lgn)适度平衡的树也称

数据结构与算法简记:AVL树

前面记录了二叉查找树,它在搜索方面的效率显而易见,可它也存在某种缺陷,假设我们连续插入较小或较大的数据,那么二叉查找树将会逐渐退变为一个线性结构,从而搜索就变为了线性查找,效率将会大打折扣.所以,我们需要一棵这样的树,它在插入新节点后,能够重新调整自己的结构,使左右恢复平衡.AVL树就符合这个条件. AVL树是最先发明的自平衡二叉查找树,其得名于它的发明者 G.M. Adelson-Velsky 和 E.M. Landis,他们在 1962 年的论文 "An algorithm for the

AVL树原理及实现(C语言实现以及Java语言实现)

欢迎探讨,如有错误敬请指正 如需转载,请注明出处http://www.cnblogs.com/nullzx/ 1. AVL定义 AVL树是一种改进版的搜索二叉树.对于一般的搜索二叉树而言,如果数据恰好是按照从小到大的顺序或者从大到小的顺序插入的,那么搜索二叉树就对退化成链表,这个时候查找,插入和删除的时间都会上升到O(n),而这对于海量数据而言,是我们无法忍受的.即使是一颗由完全随机的数据构造成的搜索二叉树,从统计角度去分析,在进行若甘次的插入和删除操作,这个搜索二叉树的高度也不能令人满意.这个

java数据结构与算法之平衡二叉树(AVL树)的设计与实现

[版权申明]未经博主同意,不允许转载!(请尊重原创,博主保留追究权) http://blog.csdn.net/javazejian/article/details/53892797 出自[zejian的博客] 关联文章: java数据结构与算法之顺序表与链表设计与实现分析 java数据结构与算法之双链表设计与实现 java数据结构与算法之改良顺序表与双链表类似ArrayList和LinkedList(带Iterator迭代器与fast-fail机制) java数据结构与算法之栈(Stack)设