AVL树

简介:  来源:http://www.cnblogs.com/JCSU/articles/2026617.html   /*******************************************************************************/* /* 版权所有    : -/* 模块名      : 查找/* 文件名      : avlTree.

 来源:http://www.cnblogs.com/JCSU/articles/2026617.html

 

复制代码
/* ******************************************************************************
/* <PRE>
/* 版权所有    : -
/* 模块名      : 查找
/* 文件名      : avlTree.cpp
/* 功能描述    : 平衡二叉树
/* 作者        : <xxx>
/* 版本        : 1.0
/* -----------------------------------------------------------------------------
/* 备注        : -
/* -----------------------------------------------------------------------------
/* 修改记录    :
/* 日 期        版本     修改人        修改内容
/* 2011/01/01   1.0      <xxx>         创建
/* </PRE>
******************************************************************************
*/
#include 
< stdio.h >
#include 
< stdlib.h >

/* *****************************************************************************
/* 数据类型和常量定义
/*****************************************************************************
*/
#define  TRUE        1
#define  FALSE       0
#define  OK          1
#define  ERROR       0

#define  LH          1 /* 左高 */ 
#define  EH          0 /* 等高 */
#define  RH         -1 /* 右高 */

typedef 
int    Status;
typedef 
int    KeyType;
typedef unsigned 
char  Boolean;

/*  数值型关键字的比较  */
#define  EQ(a, b) ((a) == (b))
#define  LT(a, b) ((a) < (b))


/* *****************************************************************************
/* 数据结构定义
/*****************************************************************************
*/
typedef 
struct  {
    KeyType key;
}ElemType;

/*  二叉排序树的类型定义  */
typedef 
struct  BSTNode {
    ElemType data;
    
int  bf;  /*  结点的平衡因子  */
    
struct  BSTNode  * lchild,  * rchild;  /*  左右孩子指针  */
} BSTNode, 
* BSTree;


/* *****************************************************************************
/* 函数原型声明
/*****************************************************************************
*/
void  R_Rotate(BSTree  & p);
void  L_Rotate(BSTree  & p);
void  RightBalance(BSTree  & T);
void  LeftBalance(BSTree  & T);
Status InsertAVL(BSTree 
& T, ElemType e, Boolean  & taller);

Status Visit(ElemType e);
Status InOrderTraverse(BSTree 
& T, Status ( * Visit)(ElemType));


/* ******************************************************************************
/* <FUNC>
/* 函数名   : R_Rotate
/* 功能     : 右旋处理
/* 参数     : -
/* 返回值   : -
/* 备注     : 对以*p为根的二叉排序树作右旋处理, 处理之后p指向新的树根结点, 即
/*            旋转处理之前的左子树的根结点
/* 作者     : <xxx>
/* </FUNC>
******************************************************************************
*/
void  R_Rotate(BSTree  & p)
{
    BSTree lc;
    lc 
=  p -> lchild;                 // lc指向的*p的左子树根结点
    p -> lchild  =  lc -> rchild;         // lc的右子树挂接为*p的左子树
    lc -> rchild  =  p;  p  =  lc;        // p指向新的根结点
}

/* ******************************************************************************
/* <FUNC>
/* 函数名   : L_Rotate
/* 功能     : 左旋处理
/* 参数     : -
/* 返回值   : -
/* 备注     : 对以*p为根的二叉排序树作左旋处理, 处理之后p指向新的树根结点, 即
/*            旋转处理之前的右子树的根结点
/* 作者     : <xxx>
/* </FUNC>
******************************************************************************
*/
void  L_Rotate(BSTree  & p)
{
    BSTree rc;
    rc 
=  p -> rchild;                 // rc指向的*p的右子树根结点
    p -> rchild  =  rc -> lchild;         // rc的左子树挂接为*p的右子树
    rc -> lchild  =  p;  p  =  rc;        // p指向新的根结点
}

/* ******************************************************************************
/* <FUNC>
/* 函数名   : InsertBST
/* 功能     : 插入元素到二叉排序树中
/* 参数     : -
/* 返回值   : -
/* 备注     : 当二叉排序树T中不存在关键字等于e.key的数据元素时, 插入e并返回TRUE,
/*            否则返回FALSE
/* 作者     : <xxx>
/* </FUNC>
******************************************************************************
*/
Status InsertAVL(BSTree 
& T, ElemType e, Boolean  & taller)
{
    
if  ( ! T) {  // 插入新结点, 树长高, taller为TRUE
        T  =  (BSTree)malloc( sizeof (BSTNode));  T -> data  =  e;
        T
-> lchild  =  T -> rchild  =  NULL;  T -> bf  =  EH;  taller  =  TRUE;
    }
    
else  {
        
if  (EQ(e.key, T -> data.key)) { taller  =  FALSE;   return   0 ; }   // 树中已存在和e有相同关键字的结点, 则不再插入
         if  (LT(e.key, T -> data.key)) {     // 应继续在*T的左子树中进行搜索
             if  ( ! InsertAVL(T -> lchild, e, taller))  return   0 ;   // 未插入
             if  (taller)  // 已插入到*T的左子树中且左子树长高
                 switch  (T -> bf) {   // 检查*T的平衡度
                    case  LH:  // 原本左子树比右子树高, 需要做左平衡处理
                      LeftBalance(T); taller  =  FALSE;  break ;
                   
case  EH:  // 原本左、右子树等高, 现因左子树增高而使树增高
                      T -> bf  =  LH; taller  =  TRUE;  break ;
                   
case  RH:  // 原本右子树比左子树高, 现在左、右子树等高
                      T -> bf  =  EH; taller  =  FALSE;  break ;
            }
        }
        
else  {   // 应继续在*T的右子树中进行搜索
             if  ( ! InsertAVL(T -> rchild, e, taller))  return   0 ;   // 未插入
             if  (taller)   // 已插入到*T的右子树中且右子树长高
                 switch  (T -> bf) {   // 检查*T的平衡度
                    case  LH:  // 原本左子树比右子树高, 现在左、右子树等高
                      T -> bf  =  EH; taller  =  FALSE;  break ;
                   
case  EH:  // 原本左、右子树等高, 现因右子树增高而使树增高
                      T -> bf  =  RH; taller  =  TRUE;  break ;
                   
case  RH:  // 原本右子树比左子树高, 需要做右平衡处理
                      RightBalance(T); taller  =  FALSE;  break ;
            }
        }
    }

    
return   1 ;
}

/* ******************************************************************************
/* <FUNC>
/* 函数名   : LeftBalance
/* 功能     : 左平衡旋转处理
/* 参数     : -
/* 返回值   : -
/* 备注     : 对以指针T所指结点为根的二叉树作左平衡旋转处理, 本算法结束时, 指针
/*            T指向新的根结点
/* 作者     : <xxx>
/* </FUNC>
******************************************************************************
*/
void  LeftBalance(BSTree  & T)
{
    BSTree lc;  BSTree rd;
    lc 
=  T -> lchild;              // lc指向*T的左子树根结点
     switch  (lc -> bf)              // 检查*T的左子树的平衡度, 并作相应平衡处理
    {
    
case  LH:                     // 新结点插入在*T的左孩子的左子树上, 要作单右旋处理
        T -> bf  =  lc -> bf  =  EH;
        R_Rotate(T);  
break ;
    
case  RH:                     // 新结点插入在*T的左孩子的右子树上, 要作双旋处理
        rd  =  lc -> rchild;         // rd指向*T人左孩子的右子树根
         switch  (rd -> bf)          // 修正*T及其左孩子的平衡因子
        {
            
case  LH:  T -> bf  =  RH;  lc -> bf  =  EH;   break ;
            
case  EH:  T -> bf  =  lc -> bf  =  EH;        break ;
            
case  RH:  T -> bf  =  EH;  lc -> bf  =  LH;   break ;
        }
        rd
-> bf  =  EH;
        L_Rotate(T
-> lchild);     // 对*T的左子树作左旋平衡处理
        R_Rotate(T);             // 对*T作右旋平衡处理
    }
}

/* ******************************************************************************
/* <FUNC>
/* 函数名   : RightBalance
/* 功能     : 右平衡旋转处理
/* 参数     : -
/* 返回值   : -
/* 备注     : 对以指针T所指结点为根的二叉树作右平衡旋转处理, 本算法结束时, 指针
/*            T指向新的根结点
/* 作者     : <xxx>
/* </FUNC>
******************************************************************************
*/
void  RightBalance(BSTree  & T)
{
    BSTree rc;  BSTree ld;
    rc 
=  T -> rchild;              // lc指向*T的右子树根结点
     switch  (rc -> bf)              // 检查*T的右子树的平衡度, 并作相应平衡处理
    {
    
case  RH:                     // 新结点插入在*T的右孩子的左子树上, 要作单左旋处理
        T -> bf  =  rc -> bf  =  EH;
        L_Rotate(T);  
break ;
    
case  LH:                     // 新结点插入在*T的右孩子的右子树上, 要作双旋处理
        ld  =  rc -> lchild;         // ld指向*T人右孩子的右子树根
         switch  (ld -> bf)          // 修正*T及其右孩子的平衡因子
        {
        
case  RH:  T -> bf  =  RH;  rc -> bf  =  EH;   break ;
        
case  EH:  T -> bf  =  rc -> bf  =  EH;        break ;
        
case  LH:  T -> bf  =  EH;  rc -> bf  =  LH;   break ;
        }
        ld
-> bf  =  EH;
        R_Rotate(T
-> rchild);     // 对*T的右子树作右旋平衡处理
        L_Rotate(T);             // 对*T作左旋平衡处理
    }
}


/* ******************************************************************************
/* <FUNC>
/* 函数名   : Visit
/* 功能     : 打印节点数据
/* 参数     : -
/* 返回值   : -
/* 备注     : -
/* 作者     : <xxx>
/* </FUNC>
******************************************************************************
*/
Status Visit(ElemType e)
{
    printf(
" %d  " , e.key);
    
return  OK;
}

/* ******************************************************************************
/* <FUNC>
/* 函数名   : InOrderTraverse
/* 功能     : 中序遍历二叉树
/* 参数     : -
/* 返回值   : -
/* 备注     : -
/* 作者     : <xxx>
/* </FUNC>
******************************************************************************
*/
Status InOrderTraverse(BSTree 
& T, Status ( * Visit)(ElemType))
{
    
if (T){
        
if (InOrderTraverse(T -> lchild, Visit))
            
if (Visit(T -> data))
                
if (InOrderTraverse(T -> rchild, Visit))
                    
return  OK;
                
return  ERROR;
    }
    
else
        
return  OK;
}


/* ******************************************************************************
/* <FUNC>
/* 函数名   : main
/* 功能     : 测试函数
/* 参数     : -
/* 返回值   : -
/* 备注     : -
/* 作者     : <xxx>
/* </FUNC>
******************************************************************************
*/
void  main()
{
    BSTree T; ElemType e;  Boolean taller;
    T 
=  NULL; 
    e.key 
=   13 ;  InsertAVL(T, e, taller);
    e.key 
=   24 ;  InsertAVL(T, e, taller);
    e.key 
=   37 ;  InsertAVL(T, e, taller);
    e.key 
=   90 ;  InsertAVL(T, e, taller);
    e.key 
=   53 ;  InsertAVL(T, e, taller);

    InOrderTraverse(T, Visit);
}
复制代码

 

 

【参考】

img_e00999465d1c2c1b02df587a3ec9c13d.jpg
微信公众号: 猿人谷
如果您认为阅读这篇博客让您有些收获,不妨点击一下右下角的【推荐】
如果您希望与我交流互动,欢迎关注微信公众号
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接。

目录
相关文章
|
9天前
|
C++
【c++】avl树
【c++】avl树
4 0
|
2月前
AVL 树
AVL 树
19 2
|
2月前
|
C++ 容器
【C++】—— 详解AVL树
【C++】—— 详解AVL树
|
2月前
|
存储 测试技术 C++
C++【AVL树】
C++【AVL树】
51 0
二叉搜索树之AVL树
二叉搜索树之AVL树
|
7月前
|
C++
C++实现AVL树
C++实现AVL树
38 0
|
算法 Java Python
实现AVL树
大家好,我是王有志。今天,我们会用Java和Python分别实现第一个平衡二分搜索树--AVL树。
66 0
实现AVL树
|
11月前
|
算法
平衡二叉树(AVL树)
平衡二叉树(AVL树)
55 0
|
C++ 容器
C++之AVL树(上)
C++之AVL树(上)
98 0

热门文章

最新文章

  • 1
    流量控制系统,用正则表达式提取汉字
    25
  • 2
    Redis09-----List类型,有序,元素可以重复,插入和删除快,查询速度一般,一般保存一些有顺序的数据,如朋友圈点赞列表,评论列表等,LPUSH user 1 2 3可以一个一个推
    26
  • 3
    Redis08命令-Hash类型,也叫散列,其中value是一个无序字典,类似于java的HashMap结构,Hash结构可以将对象中的每个字段独立存储,可以针对每字段做CRUD
    25
  • 4
    Redis07命令-String类型字符串,不管是哪种格式,底层都是字节数组形式存储的,最大空间不超过512m,SET添加,MSET批量添加,INCRBY age 2可以,MSET,INCRSETEX
    27
  • 5
    S外部函数可以访问函数内部的变量的闭包-闭包最简单的用不了,闭包是内层函数+外层函数的变量,简称为函数套函数,外部函数可以访问函数内部的变量,存在函数套函数
    23
  • 6
    Redis06-Redis常用的命令,模糊的搜索查询往往会对服务器产生很大的压力,MSET k1 v1 k2 v2 k3 v3 添加,DEL是删除的意思,EXISTS age 可以用来查询是否有存在1
    29
  • 7
    Redis05数据结构介绍,数据结构介绍,官方网站中看到
    21
  • 8
    JS字符串数据类型转换,字符串如何转成变量,+号只要有一个是字符串,就会把另外一个转成字符串,- * / 都会把数据转成数字类型,数字型控制台是蓝色,字符型控制台是黑色,
    19
  • 9
    JS数组操作---删除,arr.pop()方法从数组中删除最后一个元素,并返回该元素的值,arr.shift() 删除第一个值,arr.splice()方法,删除指定元素,arr.splice,从第一
    19
  • 10
    定义好变量,${age}模版字符串,对象可以放null,检验数据类型console.log(typeof str)
    19