重学数据结构008——AVL树

之前学习了二叉查找树的及相关操作。二叉查找树的大部分主要操作的复杂度都是O(logN)量级的。现在考虑这样一种情况:通过集合{3,2,4,1,0,-1,-2,-3,-4,-4}中的元素来构建二叉查找树,得到的树如图所示:

image

    如果现在我们需要查找元素-4,那么时间复杂度还是是O(logN)吗?有个更加极端的例子,假设数据集是{6,5,3,1,0,-1,-2,-3,-4,-4}呢?再去查找元素-4,其复杂度已经是O(N)了。也就是说,二叉查找树的查找优势完全不复存在了。在这样的情况下,以前的牛人们又想出了别的办法:让二叉查找树除了满足现有条件外,添加平衡条件,形成平衡二叉树。AVL树是其中一种典型的平衡二叉树,

    AVL树是带有平衡条件的二叉查找树。在满足所有二叉查找树条件下,还加入了平衡条件:AVl树的每个节点的左右子树的高度差必须<=1。 在我使用的这本教材中,定义空树的高度为-1,一个节点的树的高度定义为0。

   为了满足平衡条件,AVL树的基本操作一般涉及运作同在不平衡的二叉查找树所运作的同样的算法。但是要进行预先或随后做一次或多次所谓的"AVL旋转"。

涉及到的几种情况如下图所示:

Tree_Rebalancing

AVL树的基本操作代码如下:

#include <stdio.h> 
#include <stdlib.h> 
 
#define MAX(X,Y) ((X > Y) ? X : Y) 
 
typedef int ElementType; 
typedef struct AvlNode *Position; 
typedef struct AvlNode *AvlTree; 
 
/************************************************************************/ 
/* Avl树的数据结构定义以及节本操作定义                                  */ 
/************************************************************************/ 
 
struct AvlNode  
{ 
    ElementType Element; 
    int Height; 
    AvlTree Left,Right; 
}; 
 
 
AvlTree MakeEmpty(AvlTree T);                                /*清空Avl树*/ 
 
Position Find(ElementType X, AvlTree T);       /*在Avl树中查找指定的元素*/ 
 
Position FindMax(AvlTree T);                     /*在Avl树中查找最大元素*/ 
 
Position FindMin(AvlTree T);                     /*在Avl树中查找最小元素*/ 
 
AvlTree Insert(ElementType X, AvlTree T);        /*在Avl树中插入指定元素*/ 
 
AvlTree Delete(ElementType X, AvlTree T);        /*在Avl树中删除指定元素*/ 
 
ElementType Retrieve(Position P);                 /*获取指定节点的元素值*/ 
 
int Height(Position P);                           /*获得指定节点的高度值*/ 
 
Position SingleRotateWithLeft(Position P);                    /*单右旋转*/ 
 
Position SingleRotateWithRight(Position P);                   /*单左旋转*/ 
 
Position DoubleRotateWithLeft(Position P);                  /*双左右旋转*/ 
 
Position DoubleRotateWithRight(Position P);                 /*双右左旋转*/ 
 
int main(void)  
{ 
 
    return 0; 
} 
 
/************************************************************************/ 
/* 清空AVL树的操作与清空普通二叉树相同                                  */ 
/************************************************************************/ 
AvlTree MakeEmpty(AvlTree T)  
{ 
    if (!T) 
    { 
        MakeEmpty(T->Left); 
        MakeEmpty(T->Right); 
        free(T); 
    } 
    return NULL; 
} 
 
/************************************************************************/ 
/*在Avl树中查找指定的元素,与二叉查找树的操作相同                        */ 
/************************************************************************/ 
Position Find(ElementType X, AvlTree T) 
{ 
    if (T == NULL) 
    { 
        return NULL; 
    }  
    else 
    { 
        if (X < T->Element) 
        { 
            return Find(X,T->Left); 
        } 
        else if(X > T->Element) 
        { 
            return Find(X, T->Right); 
        } 
        else 
        { 
            return T; 
        } 
    } 
} 
 
/************************************************************************/ 
/* 在Avl树中查找最大值(递归写法)                                        */ 
/************************************************************************/ 
Position FindMax(AvlTree T) 
{ 
    if (T == NULL) 
    { 
        return NULL; 
    }  
    else 
    { 
        if (T->Right == NULL) 
        { 
            return NULL; 
        }  
        else 
        { 
            return FindMax(T->Right); 
        } 
    } 
} 
 
 
/************************************************************************/ 
/* 在Avl树中查找最小值(非递归写法)                                      */ 
/************************************************************************/ 
Position FindMin(AvlTree T) 
{ 
    if (T == NULL) 
    { 
        return NULL; 
    } 
    else 
    { 
        while (T->Left != NULL) 
        { 
            T = T->Left; 
        } 
        return T; 
    } 
} 
 
/************************************************************************/ 
/* 返回指定节点的高度信息                                               */ 
/************************************************************************/ 
int Height(Position P)  
{ 
    if (P == NULL) 
    { 
        return -1; 
    } 
    else 
    { 
        return P->Height; 
    } 
} 
 
/************************************************************************/ 
/* 单旋转:右旋转                                                       */ 
/* 使用条件:这个函数只适合当P有左子树时调用;                          */ 
/* 作用:在P和其左子树根节点之间执行一次单右旋转                      */ 
/************************************************************************/ 
Position SingleRotateWithLeft(Position P) 
{ 
    Position LChild = P->Left; 
    P->Left = LChild->Right;           /*将P的左孩子设置成LChild的右孩子*/ 
    LChild->Right = P; 
 
    P->Height = MAX(Height(P->Left),Height(P->Right)) + 1;/*更新高度信息*/ 
    LChild->Height = MAX(Height(LChild->Left),P->Height) + 1; 
 
    return LChild;                                          /*新的根节点*/    
} 
 
 
/************************************************************************/ 
/* 单旋转:左旋转                                                       */ 
/* 使用条件:这个函数只适合当P有右子树时调用;                           */ 
/* 作用:在P和其右子树根节点之间执行一次单左旋转                      */ 
/************************************************************************/ 
Position SingleRotateWithRight(Position P) 
{ 
    Position RChild = P->Right;        /*将P的右孩子设置成RChild的右孩子*/ 
    P->Right = RChild->Left;                                 
    RChild->Left = P; 
 
    P->Height = MAX(Height(P->Left),Height(P->Right)) + 1;/*更新高度信息*/ 
    RChild->Height = MAX(Height(RChild->Right),P->Height) + 1; 
    return RChild;                                          /*新的根节点*/ 
} 
 
 
/************************************************************************/ 
/* 双旋转:左右旋转                                                     */ 
/* 使用条件:适合于当P有左孩子,而左孩子有右孩子                        */ 
/* 作用:*/ 
/************************************************************************/ 
Position DoubleRotateWithLeft(Position P) 
{ 
    P->Left = SingleRotateWithRight(P->Left);             /*先进行左旋转*/ 
    return SingleRotateWithLeft(P);                       /*再进行又旋转*/ 
} 
 
 
/************************************************************************/ 
/* 双旋转:右左旋转                                                     */ 
/* 使用条件:适合于当P有右孩子,而右孩子有左孩子                        */ 
/* 作用:*/ 
/************************************************************************/ 
Position DoubleRotateWithRight(Position P) 
{ 
    P->Right = SingleRotateWithLeft(P->Right);            /*先进行右旋转*/ 
    return SingleRotateWithRight(P);                      /*再进行左旋转*/ 
} 
 
/************************************************************************/ 
/* AVL树插入操作                                                        */ 
/************************************************************************/ 
AvlTree Insert(ElementType X, AvlTree T) 
{ 
    /*如果T是一棵空树,那么创建一个节点作为树的根节点*/ 
    if (T == NULL) 
    { 
        T = malloc(sizeof(struct AvlNode)); 
        if(T == NULL) 
        { 
            fprintf(stderr,"Out of space!"); 
        } 
        else 
        { 
            T->Element = X; 
            T->Left = NULL; 
            T->Right = NULL; 
            T->Height = 0; 
        } 
    }else 
    { 
        if (X < T->Element) 
        { 
            T->Left = Insert(X,T->Left); 
            /*判断是否打破了破了平衡条件*/ 
            if (Height(T->Left) - Height(T->Right) == 2) 
            { 
                /*判断是四种情况中的哪一种情况*/ 
                if (X < T->Left->Element) 
                { 
                    T = SingleRotateWithLeft(T); 
                } 
                else if (X > T->Left->Element) 
                { 
                    T = DoubleRotateWithLeft(T); 
                } 
            } 
        } 
        else if (X > T->Element) 
        { 
            T->Right = Insert(X,T->Right); 
            if (Height(T->Right) - Height(T->Left) == 2) 
            { 
                if(X < T->Right->Element) 
                { 
                    T = DoubleRotateWithRight(T); 
                } 
                else if (X > T->Right->Element) 
                { 
                    T = SingleRotateWithRight(T); 
                } 
            } 
        } 
        else 
        { 
            /*元素已经存在于AVL树中,因此不需要再做别的工作*/ 
        } 
 
        /*更新数的高度信息*/ 
        T->Height = MAX(Height(T->Left),Height(T->Right)) + 1; 
 
 
     
    } 
    return T; 
} 
 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ava实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),可运行高分资源 Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现
C语言是一种广泛使用的编程语言,它具有高效、灵活、可移植性强等特点,被广泛应用于操作系统、嵌入式系统、数据库、编译器等领域的开发。C语言的基本语法包括变量、数据类型、运算符、控制结构(如if语句、循环语句等)、函数、指针等。下面详细介绍C语言的基本概念和语法。 1. 变量和数据类型 在C语言中,变量用于存储数据,数据类型用于定义变量的类型和范围。C语言支持多种数据类型,包括基本数据类型(如int、float、char等)和复合数据类型(如结构体、联合等)。 2. 运算符 C语言中常用的运算符包括算术运算符(如+、、、/等)、关系运算符(如==、!=、、=、<、<=等)、逻辑运算符(如&&、||、!等)。此外,还有位运算符(如&、|、^等)和指针运算符(如、等)。 3. 控制结构 C语言中常用的控制结构包括if语句、循环语句(如for、while等)和switch语句。通过这些控制结构,可以实现程序的分支、循环和多路选择等功能。 4. 函数 函数是C语言中用于封装代码的单元,可以实现代码的复用和模块化。C语言中定义函数使用关键字“void”或返回值类型(如int、float等),并通过“{”和“}”括起来的代码块来实现函数的功能。 5. 指针 指针是C语言中用于存储变量地址的变量。通过指针,可以实现对内存的间接访问和修改。C语言中定义指针使用星号()符号,指向数组、字符串和结构体等数据结构时,还需要注意数组名和字符串常量的特殊性质。 6. 数组和字符串 数组是C语言中用于存储同类型数据的结构,可以通过索引访问和修改数组中的元素。字符串是C语言中用于存储文本数据的特殊类型,通常以字符串常量的形式出现,用双引号("...")括起来,末尾自动添加'\0'字符。 7. 结构体和联合 结构体和联合是C语言中用于存储不同类型数据的复合数据类型。结构体由多个成员组成,每个成员可以是不同的数据类型;联合由多个变量组成,它们共用同一块内存空间。通过结构体和联合,可以实现数据的封装和抽象。 8. 文件操作 C语言中通过文件操作函数(如fopen、fclose、fread、fwrite等)实现对文件的读写操作。文件操作函数通常返回文件指针,用于表示打开的文件。通过文件指针,可以进行文件的定位、读写等操作。 总之,C语言是一种功能强大、灵活高效的编程语言,广泛应用于各种领域。掌握C语言的基本语法和数据结构,可以为编程学习和实践打下坚实的基础。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值