`

【查找结构3】平衡二叉查找树 [AVL]

阅读更多

在上一个专题中,我们在谈论二叉查找树的效率的时候。不同结构的二叉查找树,查找效率有很大的不同(单支树结构的查找效率退化成了顺序查找)。如何解决这个问题呢?关键在于如何最大限度的减小树的深度。正是基于这个想法,平衡二叉树出现了。

 

平衡二叉树的定义 (AVL—— 发明者为Adel'son-Vel'skii 和 Landis)

 

平衡二叉查找树,又称 AVL树。 它除了具备二叉查找树的基本特征之外,还具有一个非常重要的特点: 的左子树和右子树都是平衡二叉树,且左子树和右子树的深度之差的绝对值平衡因子 不超过1。 也就是说AVL树每个节点的平衡因子只可能是-1、0和1(左子树高度减去右子树高度)。

 

那么如何是二叉查找树在添加数据的同时保持平衡呢?基本思想就是:当在二叉排序树中插入一个节点时,首先检查是否因插入而破坏了平衡,若 破坏,则找出其中的最小不平衡二叉树,在保持二叉排序树特性的情况下,调整最小不平衡子树中节点之间的关系,以达 到新的平衡。所谓最小不平衡子树 指离插入节点最近且以平衡因子的绝对值大于1的节点作为根的子树。

 

平衡二叉树的操作

 

1. 查找操作

       平衡二叉树的查找基本与二叉查找树相同。

 

2. 插入操作

       在平衡二叉树中插入结点与二叉查找树最大的不同在于要随时保证插入后整棵二叉树是平衡的。那么调整不平衡树的基本方法就是: 旋转 下面我们归纳一下平衡旋转的4中情况

1) 绕某元素左旋转  

                                 80                                    90  

                                 /  \             左旋               /    \

                               60 90          ---- ->         80     120

                                    /  \                               /  \       /

                                  85 120                    60  85 100

                                        /

                                      100     

                               a)  BST树                              b ) AVL树

     分析一下:在插入数据100之前,a图的B ST树只有80节点的平衡因子是-1(左高-右高),但整棵树还是平衡的。加入100之后,80节点的平衡因子就成为了-2,此时平衡被破坏。需要左旋转成b 图。

     当树中节点X的右孩子的右孩子上插入新元素,且平衡因子从-1变成-2后,就需要绕节点X进行左旋转。

 

2) 绕某元素右旋转  

                                100                                   85

                                 /  \               右旋              /    \

                              85  120         ------ ->     60    100  

                              /  \                                      \      /   \

                            60 90                                 80  90 120

                              \

                              80

                             a) B ST树                                b) AVL树

     当树中节点X的左孩子的左孩子上插入新元素,且平衡因子从1变成2后,就需要绕节点X进行右旋转。

 

3) 绕某元素的左子节点左旋转,接着再绕该元素自己右旋转。 此情况下就是左旋与右旋 的结合,具体操作时可以分 解成这两种操作,只是围绕点不一样而已。

                                                      

                            100                             100                                90

                             /  \             左旋            /  \              右旋           /    \

                          80  120       ------>      90  120        ------>     80   100  

                          / \                                  /                                    /  \      \

                       60 90                            80                              60  85  120

                            /                               / \

                          85                            60 85

      当树中节点X的左孩子的右孩子上插入新元素,且 平衡因子从1变成2后,就需要 先绕X的左子节点Y左旋转,接着再绕X右旋转


4) 绕某元素的右子节点右旋转,接着再绕该元素自己左旋转。 此情况下就是 右旋与左旋 的结合,具体操作时可以分解 成这两种操作,只是围绕点不一样而已

 

                               80                               80                                       85  

                               /   \             旋          /  \                             /  \     

                            60  100      ------>      60 85            ------->          80 100

                                   /  \                                 \                                   /     /   \       

                                85  120                        100                           60    90 120

                                   \                                   /  \

                                   90                           90  120

       当树中节点X的右孩子的左孩子上插入新元素,且 平衡因子从-1变成-2后,就需要 先绕X的右子节点Y右旋转,接着再绕X左旋转

 

 

平衡二叉树性能分析


平衡二叉树的性能优势:

      很显然,平衡二叉树的优势在于不会出现普通二叉查找树的最差情况。其查找的时间复杂度为O(logN)。

 

平衡二叉树的缺陷:

      (1) 很遗憾的是,为了保证高度平衡,动态插入和删除的代价也随之增加。因此,我们在下一专题中讲讲《红黑树》 这种更加高效的查找结构。

 

      (2) 所有二叉查找树结构的查找代价都与树高是紧密相关的,能否通过减少树高来进一步降低查找代价呢。我们可以通过多路查找树的结构来做到这一点,在后面专题中我们将通过《多路查找树/B-树/B+树 》来介绍。

 

      (3) 在大数据量查找环境下(比如说系统磁盘里的文件目录,数据库中的记录查询 等),所有的二叉查找树结构(BST、AVL、RBT)都不合适。如此大规模的数据量(几G数据),全部组织成平衡二叉树放在内存中是不可能做到的。那么把这棵树放在磁盘中吧。问题就来了:假如构造的平衡二叉树深度有1W层。那么从根节点出发到叶子节点很可能就需要1W次的硬盘IO读写。大家都知道,硬盘的机械部件读写数据的速度远远赶不上纯电子媒体的内存。 查找效率在IO读写过程中将会付出巨大的代价。在大规模数据查询这样一个实际应用背景下,平衡二叉树的效率就很成问题了。对这一问题的解决:我们也会在《多路查找树/B-树/B+树 》 将详细分析。

 

      上面提到的红黑树和多路查找树都是属于深度有界查找树(depth-bounded tree —DBT)


平衡二叉树的插入操作代码(平衡旋转)

package net.hr.algorithm.search;
/**平衡因子枚举类*/
enum B
alanceFactor{
	LH("左子树高"),EH("左右等高"),RH("右子树高");
	
	private String illustration="";
	
	private BalanceFactor(String s){
		this.illustration=s;
	}
	
	public String toString(){
		return this.illustration;
	}
}
/**
 * 平衡二叉树结点
 */
class AVLNode<E extends Comparable<E>>{
	/**结点关键字*/
	E key=null;
	/**结点的平衡因子*/
	BalanceFactor bFactor=BalanceFactor.EH;
	/**结点的直接父亲*/
	AVLNode<E> parent=null;
	/**结点的左右孩子*/
	AVLNode<E> lchild,rchild=null;
	
	AVLNode(E k){
		this.key=k;
	}
	/**
	 * 格式输出结点
	 */
	public String toString(){
		//String fomateStr="";
		//if(this.lchild==null)
		String lchildStr=(this.lchild==null)?"null":this.lchild.key.toString();
		String rchildStr=(this.rchild==null)?"null":this.rchild.key.toString();
		return this.key+"[lchild="+lchildStr+",rchild="+rchildStr+"]";
	}

}
/**
 * 平衡二叉查找树
 * @author heartraid
 */
public class AVL<E extends Comparable<E>> {

	/**树根*/
	private AVLNode<E> root=null;
	/**当前树是否变高*/
	public boolean isTaller=false;
	
	public AVL(){
	}
	
	
	public boolean insert(E key){
		System.out.print("插入["+key+"]:");
		if(key==null) return false;
		if(root==null){
			System.out.println("插入到树根。");
			root=new AVLNode<E>(key);
			return true;
		}
		else{
			System.out.print("搜索路径[");
			return insertAVL(key,root);
		}
	}
	
	private boolean insertAVL(E key,AVLNode<E> node){
		System.out.print(node.key+" —>");
		// 树中存在相同的key,不需要插入
		if(node.key.compareTo(key)==0){
			System.out.println("].  搜索有相同关键字,插入失败");
			isTaller=false;
			return false;
		}
		else{
			//左子树搜索
			if(node.key.compareTo(key)>0){
				//当前node的左孩子为空,则插入到结点的做孩子并修改结点的平衡因子为LH
				if(node.lchild==null){
					System.out.println("].  插入到"+node.key+"的左孩子");
					AVLNode<E> newNode=new AVLNode<E>(key);
					node.lchild=newNode; //设置左孩子结点
					newNode.parent=node; //设置父亲结点
					isTaller=true; //树长高了
				}
				//左孩子不为空,则继续搜索下去
				else{
					insertAVL(key,node.lchild);
				}
				//当前如果树长高了,说明是因为左孩子的添加改变了平衡因子(左高)。
				if(isTaller){
					System.out.print("          树变化了,"+node.key+"的平衡因子变化");
					switch(node.bFactor){
					    //原来结点平衡因子是LH(bf=1),则左高以后bf=2,因此需要做左平衡旋转
						case LH: {
							System.out.println("[LH=1 ——> LH=2]. 出现了不平衡现象[左比右高2]");
							System.out.println("          ★ 以"+node.key+"为根将树进行左平衡处理");
							leftBalance(node);
							isTaller=false; 
							break;
						}
						//原来结点平衡因子是EH(bf=0),则左高了以后bf=1,不需要平衡处理。
						case EH:{
							System.out.println("[EH=0 ——> LH=1]. 没有不平衡现象");
							node.bFactor=BalanceFactor.LH;
							isTaller=true;
							break;
						}
						//原来结点平衡因子是RH(bf=-1),则左高以后bf=0,不需要平衡处理。
						case RH:{
							System.out.println("[RH=-1 ——> EH=0]. 没有不平衡现象");
							node.bFactor=BalanceFactor.EH;
							isTaller=false;
							break;
						}
					}//end switch
				}//end if
			}//end if
			//右子树搜索
			else{
				if(node.rchild==null){
					System.out.println("].  插入到"+node.key+"的右孩子");
					AVLNode<E> newNode=new AVLNode<E>(key);
					node.rchild=newNode; //设置右孩子结点
					newNode.parent=node; //设置父亲结点
					isTaller=true; //树长高了
				}
				else{
					insertAVL(key,node.rchild);
				}
				//当前如果树长高了,说明是因为右孩子的添加改变了平衡因子(右高)。
				if(isTaller){
					System.out.print("          树变化了,"+node.key+"的平衡因子变化");
					switch(node.bFactor){
					    //原来结点平衡因子是LH(bf=1),则右高以后bf=0,不需要平衡处理。
						case LH: {
							System.out.println("[LH=1 ——> EH=0]. 没有不平衡现象");
							node.bFactor=BalanceFactor.EH;
							isTaller=false;
							break;
						}
						//原来结点平衡因子是EH(bf=0),则右高了以后bf=-1,不需要平衡处理。
						case EH:{
							System.out.println("[EH=0 ——> RH=-1]. 没有不平衡现象");
							node.bFactor=BalanceFactor.RH;
							isTaller=true;
							break;
						}
						//原来结点平衡因子是RH(bf=-1),则右高以后bf=0,因此需要做右平衡旋转。
						case RH:{
							System.out.println("[RH=-1 ——> RH=-2]. 出现了不平衡现象[左比右矮2]");
							rightBalance(node);
							isTaller=false; 
							break;
						}
					}//end switch
				}//end if(isTaller)
			}//end else
			return true;
		}//end else
	}
	/**
	 * 左平衡旋转处理
	 * 先对node的左子树进行单左旋处理,在对node树进行单右旋处理
	 * 
	 *     100                      100                     90
         *     /  \           左旋       /  \          右旋     /  \
         *    80  120   ------>  90  120   ------> 80  100  
         *   / \                         /                        /  \     \
         *  60 90                   80                     60  85  120
         *     /                        / \
         *    85                    60 85
	 * 
	 * @param node 需要做处理的子树的根结点
	 */
	private void leftBalance(AVLNode<E> node){
		// node.parent指向新的孩子结点
		AVLNode<E> lc=node.lchild;//lc指向node的左孩子结点
		switch(lc.bFactor){
			case LH:{  //新结点插入在node的左孩子的左子树上,则需要单右旋处理
				System.out.println("           ┖ 对"+node.key+"进行单右旋转处理");
				node.bFactor=lc.bFactor=BalanceFactor.EH;
				rRotate(node);
				break;
			}
			case RH:{  //新结点插入在node的左孩子的右子树上,需要双旋处理
				System.out.println("            ┖ 对"+node.key+"的左子树进行单左旋转处理,再对其本身树进行单右循环处理");
				AVLNode<E> rd=lc.rchild; //rd指向node左孩子的右子树根
				switch(rd.bFactor){ //修改node与其左孩子的平衡因子
					case LH:{
						node.bFactor=BalanceFactor.RH;
						lc.bFactor=BalanceFactor.EH;
						break;
					}
					case EH:{
						node.bFactor=lc.bFactor=BalanceFactor.EH;
						break;
					}
					case RH:{
						node.bFactor=BalanceFactor.EH;
						lc.bFactor=BalanceFactor.LH;
						break;
					}
				}//switch
				rd.bFactor=BalanceFactor.EH;
				lRotate(node.lchild);
				rRotate(node);
				break;
			}
		}
		
	}
	/**
	 * 右平衡旋转处理
	 * 
	 *    80                         80                        85  
         *   /  \            右 旋      /  \        左 旋        /  \     
         *  60  100    ------>  60   85   ------->   80  100
         *      /  \                       \                       /   /  \       
         *     85  120                100                 60  90  120
         *      \                          /  \
         *      90                     90  120 
	 * 
	 * @param node
	 */
	private void rightBalance(AVLNode<E> node){
		AVLNode<E> lc=node.rchild;//lc指向node的右孩子结点
		switch(lc.bFactor){
			case RH:{  //新结点插入在node的右孩子的右子树上,则需要单左旋处理
				node.bFactor=lc.bFactor=BalanceFactor.EH;
				lRotate(node);
				break;
			}
			case LH:{  //新结点插入在node的右孩子的左子树上,需要双旋处理
				AVLNode<E> rd=lc.lchild; //rd指向node右孩子的左子树根
				switch(rd.bFactor){ //修改node与其右孩子的平衡因子
					case LH:{
						node.bFactor=BalanceFactor.EH;
						lc.bFactor=BalanceFactor.RH;
						break;
					}
					case EH:{
						node.bFactor=lc.bFactor=BalanceFactor.EH;
						break;
					}
					case RH:{
						node.bFactor=BalanceFactor.LH;
						lc.bFactor=BalanceFactor.EH;
						break;	
					}
				}//switch
				rd.bFactor=BalanceFactor.EH;
				rRotate(node.rchild);
				lRotate(node);
				break;
			}
		}
	}
	
	
	/**
	 * 对以node为根的子树进行单右旋处理,处理后node.parent指向新的树根,即旋转之前
	 * node的左孩子结点
	 *      100<-node.parent           80<-node.parent
	 *      /                                      /  \
	 *     80             ———>         60   100
	 *    /  \                                  /
	 *   60  85                            85
	 */
	private void rRotate(AVLNode<E> node){
		
		AVLNode<E> lc=node.lchild;//lc指向node的左孩子结点
		
		node.lchild=lc.rchild;
		lc.rchild=node;
		if(node.parent==null){
			root=lc;
		}
		else if(node.parent.lchild.key.compareTo(node.key)==0)
			node.parent.lchild=lc;
		else node.parent.rchild=lc;
	}
	/**
	 * 对以node为根的子树进行单左旋处理,处理后node.parent指向新的树根,即旋转之前
	 * node的右孩子结点
	 *      100<-node.parent        110<-node.parent
	 *        \                                  /  \
	 *        110        ————>   100  120
	 *        /  \                               \
	 *      105  120                      105
	 */
	private void lRotate(AVLNode<E> node){
		AVLNode<E> rc=node.rchild;//lc指向node的右孩子结点
		node.rchild=rc.lchild;
		rc.lchild=node;
		if(node.parent==null){
			root=rc;
			
		}
		else if(node.parent.lchild.key.compareTo(node.key)==0)
			    node.parent.lchild=rc;
		else node.parent.rchild=rc;
	}
	
	/**
	 * 得到BST根节点
	 * @return BST根节点f
	 */
    public AVLNode<E> getRoot(){
    	return this.root;
    }
 
	/**
	 * 递归前序遍历树
	 */
	public void preOrderTraverse(AVLNode<E> node){
		if(node!=null){
			System.out.println(node);
			preOrderTraverse(node.lchild);
			preOrderTraverse(node.rchild);
		}
	}
	/**
	 * 测试
	 * @param args
	 */
	public static void main(String[] args) {
		AVL<Integer> avl=new AVL<Integer>();
		avl.insert(new Integer(80));
		avl.insert(new Integer(60));
		avl.insert(new Integer(90));
		avl.insert(new Integer(85));
		avl.insert(new Integer(120));
		avl.insert(new Integer(100));
	
		System.out.println("前序遍历AVL:");
		avl.preOrderTraverse(avl.getRoot());

	}
}

 

 

相关问题1:N层平衡二叉树至少多少个结点

 

假设F(N)表示N层平衡二叉树的结点个数,则F[1]=1,F[2]=2。而F(N)=F(N-2)+F(N-1)+1

 

为什么呢?我们可以这样考虑,假设现在又一个(N-2)层和(N-1)层的最少结点平衡二叉树。要构造一棵N层的平衡二叉树,则只需加入一个根节点,其左右子树分别(N-2)层和(N-1)层的树即可 。由于两个子树都是最少结点的,所有N层的也是最少结点的。

 

9
2
分享到:
评论
5 楼 Garfieldwsh 2013-10-12  
202-205行的情况可能出现吗?我没想明白,可以讲讲吗?~谢谢!~
4 楼 liubida 2012-03-06  
*Rotate的指针移动都没考虑parent

private void lRotate(AVLNode<E> node){  
        AVLNode<E> rc=node.rchild;//lc指向node的右孩子结点  

        node.rchild=rc.lchild;  
        rc.lchild=node;  

        //fixme:上面两行, rc和node的parent都没做修改,
        //导致再次rotate的时候, 这里的node.parent还是以前的parent
        if(node.parent==null){  
            root=rc;                
        }  
        else if(node.parent.lchild.key.compareTo(node.key)==0)  
                node.parent.lchild=rc;  
        else node.parent.rchild=rc;  
    }
3 楼 irshinning 2011-11-17  
不知道是不是我没搞明白
如果某节点的左孩子为null,且左树高,往树上插左孩子应该判断该节点的右孩子是不是为null,不然怎么知道左孩子插了之后平衡因子就变为2了呢
2 楼 jnullpointer 2010-08-31  
能不能讲解一下删除的算法?
1 楼 lixia0417 2010-08-09  
楼主:我觉得这里的递归有问题:  
                 newNode.parent=node; //设置父亲结点  
                    isTaller=true; //树长高了  
                }  
                //左孩子不为空,则继续搜索下去  
                else{  
                    insertAVL(key,node.lchild);  
                }  
                //当前如果树长高了,说明是因为左孩子的添加改变了平衡因子(左高)。  
                if(isTaller){  
                    System.out.print("          树变化了,"+node.key+"的平衡因子变化");  
                   
我总觉得是不论递归怎么返回,后面的istaller都为true,即都会执行if里面的语句,我认为应该是把判断移到里面:这样:    newNode.parent=node; //设置父亲结点  
                    isTaller=true; //树长高了 
                   if(isTaller){  
                    System.out.print("          树变化了,"+node.key+"的平衡因子变化");    
                //左孩子不为空,则继续搜索下去  

                else{  
                    insertAVL(key,node.lchild);  
                }  
  
               

相关推荐

    数据结构(二叉平衡排序树)课程设计报告

    你可能还需要讨论可能的优化方法,如引入其他类型的平衡树(如Splay树、B树或B+树)进行对比,以及在特定场景下它们各自的适用性。 通过这次课程设计,你不仅将深入理解二叉平衡排序树的原理,还将锻炼到实际问题的...

    AVL树数据结构平衡二叉查找树

    在计算机科学中,AVL树是最先发明的自平衡二叉查找树。在AVL树中任何节点的两个子树的高度最大差别为1,所以它也被称为高度平衡树。增加和删除可能需要通过一次或多次树旋转来重新平衡这个树。AVL树得名于它的发明者...

    数据结构课程设计 二叉排序树与平衡二叉排序树

    在数据结构的学习中,二叉排序树(Binary Search Tree,BST)是一种常见的树形数据结构,它具有查找、插入和删除等操作的高效性。在这个课程设计中,我们将重点探讨如何利用二叉链表作为存储结构来实现二叉排序树,...

    C#,自平衡二叉查找树(AVL Tree)的算法与源代码

    自平衡二叉查找树(AVL Tree)中任何节点的两个子树的高度最大差别为1,所以它也被称为高度平衡树。增加和删除可能需要通过一次或多次树旋转来重新平衡这个树。AVL树得名于它的发明者G. M. Adelson-Velsky和E. M. ...

    数据结构课程设计\二叉平衡排序树

    McCreight于1972年提出,是一种自平衡二叉查找树。红黑树的每个节点都有一个颜色属性,可以是红色或黑色,通过特定的规则保持平衡,确保最坏情况下的搜索、插入和删除操作时间复杂度为O(log n)。 3. Splay树:...

    数据结构-用户登录实验-二叉查找树AVL树实现

    总之,这个实验深入探讨了数据结构中的一个重要部分,即二叉查找树和AVL树的理论与实践。通过这样的实验,学生可以更好地理解数据结构的原理,提高编程技能,同时为解决实际问题如数据库索引、文件系统等打下坚实...

    数据结构平衡二叉排序树

    在本实验中,我们主要探讨的是数据结构中的一个关键概念——平衡二叉排序树(Balanced Binary Sort Tree),也称为AVL树。AVL树是一种自平衡的二叉搜索树,它的每个节点都包含一个平衡因子,这个因子是该节点的左...

    平衡二叉排序树的算法实现

    2. **红黑树**:红黑树是一种自平衡的二叉查找树,由R. H. Sedgewick提出。它的每个节点都有颜色属性,可以是红色或黑色,满足以下性质:根节点是黑色;所有叶子节点(NIL节点)是黑色;如果一个节点是红色,则其子...

    数据结构实验之二叉排序树

    实验过程中,应该注意代码的清晰性和效率,同时理解各种操作对树形状的影响,以及如何维护二叉排序树的平衡,以优化查找性能。 总结来说,"数据结构实验之二叉排序树"是一个实践性的学习项目,旨在通过动手实现二叉...

    二叉排序树和折半查找

    二叉排序树在查找过程中类似于连续的折半查找,只不过是在树结构中进行,而折半查找是在数组中进行。 8. **应用**: 二叉排序树广泛用于数据库索引、文件系统和虚拟内存管理等场景,而折半查找常用于大量有序数据...

    C语言写的平衡二叉排序树

    3. **查找操作**:在平衡二叉排序树中查找一个元素是相当简单的。从根节点开始,如果目标键小于当前节点的键,我们向左子树移动;如果目标键大于当前节点的键,我们向右子树移动。这个过程一直持续到找到目标节点...

    GNU的自平衡二叉查找树(AVL tree、redblack tree等)源代码

    自平衡二叉查找树(Self-balancing Binary Search Tree,简称SBST)是计算机科学中用于高效数据存储的数据结构。它们确保了在最坏情况下的搜索、插入和删除操作的时间复杂度为O(log n),其中n是树中的节点数。在这个...

    c++源代码平衡二叉排序树

    5. **平衡调整**:在插入或删除节点后,可能需要通过旋转操作来重新平衡树,以保持O(log n)的性能。 6. **线索化**:对普通二叉排序树进行线索化,使得在树中进行前序、中序和后序遍历时,可以沿着线索前进。 这个...

    数据结构二叉平衡树课程设计

    二叉平衡树是一种特殊类型的二叉树,它在保持二叉搜索树特性的同时,通过特定的结构调整策略确保了树的高度平衡。这样的平衡状态使得在树中进行查找、插入和删除等操作的时间复杂度都能保持在对数级别,极大地提高了...

    二叉平衡树学生管理系统

    这个系统基于二叉平衡树的数据结构,如AVL树或红黑树,以确保数据操作(如查找、插入和删除)的高效性。下面我们将深入探讨其中涉及的主要知识点。 1. **二叉平衡树**: 二叉平衡树是一种特殊的二叉树,其左右子树...

    二叉排序树查找算法

    二叉排序树(Binary Search Tree,BST),也称为二叉查找树或有序二叉树,是一种自平衡的二叉树数据结构,它在处理搜索、插入和删除操作时具有较高的效率。二叉排序树的主要特点是:对于任意节点,其左子树中的所有...

    数据结构课程设计二叉排序树的实现

    二叉排序树(Binary Search Tree, BST),又称二叉查找树或有序二叉树,是一种特殊的二叉树,其特点在于对于任意节点而言,其左子树中的所有节点的值均小于该节点的值,而右子树中的所有节点的值均大于该节点的值。...

    二叉查找树+AVL树.zip

    AVL树是一种自平衡的二叉查找树,它的主要特点是任何节点的两个子树的高度最大差为1,这确保了树的平衡性。通过旋转操作(左旋、右旋),AVL树可以快速地在插入和删除节点后重新平衡,从而保持高效的查找性能,最坏...

    VC++2012编程演练数据结构《9》平衡二叉搜索树

    3. `AVLTREE.h`:这个文件可能包含了AVL树的数据结构定义和相关操作函数,如插入、删除、平衡调整等。 4. `StdAfx.h`:预编译头文件的对应头文件,通常包含了一些常用的库引用。 5. `9.sln`:这是Visual Studio解决...

    平衡二叉查找树算法代码

    平衡二叉查找树(Balanced Binary Search Tree,简称BBST)是一种特殊的二叉树数据结构,它的主要特点是每个节点的两个子树的高度差不超过1,这使得在树中的搜索、插入和删除操作都能保持较高的效率,通常为O(log n)...

Global site tag (gtag.js) - Google Analytics