数据结构实验之查找二:平衡二叉树

think:
1 今天学习了平衡二叉树的知识,感觉还是不理解,自己照着部分模板敲了代码,但是也不知道自己的学习方法对不对,不知道自己是不是有点拔苗助长的滋味,数据结构树的部分,从最开始的二叉树的遍历,到搜索二叉树,再到现在的平衡二叉树,感觉自己有很多细节并没有理解,很多时候感觉可能只会用一些模板,而对其深刻的思想却领悟的并不透彻,数据结构从开始的线性表,感觉自己并没有脚踏实地的一步一步走坚固,或许自己最初应该从指针开始打下坚固的地基,否则感觉自己愈行愈艰难,知识体系的建立犹如不断抛出自己手中的锚,将之前接触到学习到的知识与自己当前学习的知识联系起来,逐渐得到一种融会贯通的效果。下面进入联系题目的空间吧。

sdut原题链接

数据结构实验之查找二:平衡二叉树
Time Limit: 400MS Memory Limit: 65536KB

Problem Description
根据给定的输入序列建立一棵平衡二叉树,求出建立的平衡二叉树的树根。

Input
输入一组测试数据。数据的第1行给出一个正整数N(n <= 20),N表示输入序列的元素个数;第2行给出N个正整数,按数据给定顺序建立平衡二叉树。

Output
输出平衡二叉树的树根。

Example Input
5
88 70 61 96 120

Example Output
70

Hint

Author
xam

以下为accepted建议参考代码

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define Max(a, b) (a > b? a: b)
typedef struct node
{
    int Data;
    int Hight;//树高
    struct node *left;
    struct node *right;
} AVLTree;
int GetHight(AVLTree *T)
{
    if(T)
        return T->Hight;
    else
        return 0;
}
AVLTree * SingleLeftRotation(AVLTree *A)
{   /* A必须有一个左子结点B*/
    /* 将A与B左单旋,更新A与B的高度,返回新的根结点*/
    AVLTree *B = A->left;
    A->left = B->right;
    B->right = A;
    A->Hight = Max(GetHight(A->left), GetHight(A->right)) + 1;
    B->Hight = Max(GetHight(B->left), A->Hight) + 1;
    return B;
}
AVLTree * SingleRightRotation(AVLTree *A)
{
    /* A必须有一个右子结点B*/
    /* 讲A与B做右单旋,更新A与B的高度,返回新的根结点B*/
    AVLTree *B = A->right;
    A->right = B->left;
    B->left = A;
    A->Hight = Max(GetHight(A->left), GetHight(A->right)) + 1;
    B->Hight = Max(GetHight(B->left), A->Hight) + 1;
    return B;
}
AVLTree * DoubleLeftRightRotation(AVLTree *A)
{   /* A必须有一个左子结点B, 且B必须有一个右子结点C*/
    /* 将A, B, C做两次单旋,返回新的根结点C*/

    /* 将B与C做右单旋, C被返回*/
    A->left = SingleRightRotation(A->left);
    /* 将A与C做左单旋, C被返回*/
    return SingleLeftRotation(A);
}
AVLTree * DoubleRightLeftRotation(AVLTree *A)
{   /* A必须有一个右子结点B, 且B必须有一个左子结点C*/
    /* 将A, B, C做两次单旋,返回新的根结点C*/

    /* 将B与C做左单旋, C被返回*/
    A->right = SingleLeftRotation(A->right);
    /* 将A与C做右单旋, C被返回*/
    return SingleRightRotation(A);
}
AVLTree * Insert(AVLTree *T, int x)//将x插入AVL树中,并且返回调整后的AVL树
{
    if(T == NULL)
    {
        T = (AVLTree *)malloc(sizeof(AVLTree));
        T->Data = x;
        T->Hight = 1;
        T->left = T->right = NULL;
    }
    else if(x < T->Data)
    {
        T->left = Insert(T->left, x);
        if(GetHight(T->left) - GetHight(T->right) == 2)
        {
            if(x < T->left->Data)
                T = SingleLeftRotation(T);
            else
                T = DoubleLeftRightRotation(T);
        }
    }
    else if(x > T->Data)
    {
        T->right = Insert(T->right, x);
        if(GetHight(T->left) - GetHight(T->right) == -2)
        {
            if(x > T->right->Data)
                T = SingleRightRotation(T);
            else
                T = DoubleRightLeftRotation(T);
        }
    }
    T->Hight = Max(GetHight(T->left), GetHight(T->right)) + 1;
    return T;
}
int main()
{
    int n, i, x;
    AVLTree *root = NULL;//定义和初始化
    scanf("%d", &n);
    for(i = 0; i < n; i++)
    {
        scanf("%d", &x);
        root = Insert(root, x);//插入
    }
    printf("%d\n", root->Data);//输出最终AVL树的根结点
    return 0;
}


/***************************************************
User name: jk160630
Result: Accepted
Take time: 0ms
Take Memory: 108KB
Submit time: 2017-02-12 14:59:55
****************************************************/

一下为accepted代码—有疑问数据

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define Max(a, b) (a > b? a: b)
typedef struct node
{
    int Data;
    int Hight;//树高
    struct node *left;
    struct node *right;
} AVLTree;
int GetHight(AVLTree *T)
{
    if(T)
        return T->Hight;
    else
        return 0;
}
AVLTree * SingleLeftRotation(AVLTree *A)
{   /* A必须有一个左子结点B*/
    /* 将A与B左单旋,更新A与B的高度,返回新的根结点*/
    AVLTree *B = A->left;
    A->left = B->right;
    B->right = A;
    A->Hight = Max(GetHight(A->left), GetHight(A->right)) + 1;
    B->Hight = Max(GetHight(B->left), A->Hight) + 1;
    return B;
}
AVLTree * SingleRightRotation(AVLTree *A)
{
    /* A必须有一个右子结点B*/
    /* 讲A与B做右单旋,更新A与B的高度,返回新的根结点B*/
    AVLTree *B = A->right;
    A->right = B->left;
    B->left = A;
    A->Hight = Max(GetHight(A->left), GetHight(A->right)) + 1;
    B->Hight = Max(GetHight(B->left), A->Hight) + 1;
    return B;
}
AVLTree * DoubleLeftRightRotation(AVLTree *A)
{   /* A必须有一个左子结点B, 且B必须有一个右子结点C*/
    /* 将A, B, C做两次单旋,返回新的根结点C*/

    /* 将B与C做右单旋, C被返回*/
    A->left = SingleRightRotation(A->left);
    /* 将A与C做左单旋, C被返回*/
    return SingleLeftRotation(A);
}
AVLTree * DoubleRightLeftRotation(AVLTree *A)
{   /* A必须有一个右子结点B, 且B必须有一个左子结点C*/
    /* 将A, B, C做两次单旋,返回新的根结点C*/

    /* 将B与C做左单旋, C被返回*/
    A->right = SingleLeftRotation(A->right);
    /* 将A与C做右单旋, C被返回*/
    return SingleRightRotation(A);
}
AVLTree * Insert(AVLTree *T, int x)//将x插入AVL树中,并且返回调整后的AVL树
{
    if(T == NULL)
    {
        T = (AVLTree *)malloc(sizeof(AVLTree));
        T->Data = x;
        T->Hight = 1;
        T->left = T->right = NULL;
    }
    else if(x < T->Data)
    {
        T->left = Insert(T->left, x);
        if(GetHight(T->left) - GetHight(T->right) == 2)
        {
            if(x < T->left->Data)
                T = SingleLeftRotation(T);
            else
                T = DoubleLeftRightRotation(T);
        }
    }
 ///else if(x > T->Data)
    else
    {
        T->right = Insert(T->right, x);
        if(GetHight(T->left) - GetHight(T->right) == -2)
        {
            if(x > T->right->Data)
                T = SingleRightRotation(T);
            else
                T = DoubleRightLeftRotation(T);
        }
    }
    T->Hight = Max(GetHight(T->left), GetHight(T->right)) + 1;
    return T;
}
int main()
{
    int n, i, x;
    AVLTree *root = NULL;//定义和初始化
    scanf("%d", &n);
    for(i = 0; i < n; i++)
    {
        scanf("%d", &x);
        root = Insert(root, x);//插入
    }
    printf("%d\n", root->Data);//输出最终AVL树的根结点
    return 0;
}


/***************************************************
User name: jk160630
Result: Accepted
Take time: 0ms
Take Memory: 116KB
Submit time: 2017-02-12 15:01:15
****************************************************/

疑问数据:
5
88 70 61 96 96(存在重复元素)

以下为Accepted代码

#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

struct Tree{
    int x, h;
    Tree *left;
    Tree *right;
}*root;

int get_h(Tree *rt);
Tree * insert_x(Tree *rt, int x);
Tree * L_L(Tree *rt);
Tree * R_R(Tree *rt);
Tree * L_R(Tree *rt);
Tree * R_L(Tree *rt);
void del_meo(Tree *rt);

int main(){
    int n, i, x;
    while(~scanf("%d", &n)){
        root = NULL;
        for(i = 0; i < n; i++){
            scanf("%d", &x);
            root = insert_x(root, x);
        }
        printf("%d\n", root->x);
        del_meo(root);
    }
    return 0;
}
int get_h(Tree *rt){
    if(rt == NULL) return 0;
    else return rt->h;
}
Tree * insert_x(Tree *rt, int x){
    if(rt == NULL){
        rt = new Tree;
        rt->x = x;
        rt->h = 1;
        rt->left = rt->right = NULL;
    }
    else if(x < rt->x){
        rt->left = insert_x(rt->left, x);
        if(get_h(rt->left) - get_h(rt->right) == 2){
            if(x < (rt->left)->x)
                rt = L_L(rt);
            else
                rt = L_R(rt);
        }
    }
    else if(x > rt->x){
        rt->right = insert_x(rt->right, x);
        if(get_h(rt->left) - get_h(rt->right) == -2){
            if(x > (rt->right)->x)
                rt = R_R(rt);
            else
                rt = R_L(rt);
        }
    }
    rt->h = max(get_h(rt->left), get_h(rt->right)) + 1;
    return rt;
}
Tree * L_L(Tree *rt){
    Tree *a = rt, *b = rt->left;
    a->left = b->right;
    b->right = a;
    a->h = max(get_h(a->left), get_h(a->right)) + 1;
    b->h = max(get_h(b->left), get_h(b->right)) + 1;
    return b;
}
Tree * R_R(Tree *rt){
    Tree *a = rt, *b = rt->right;
    a->right = b->left;
    b->left = a;
    a->h = max(get_h(a->left), get_h(a->right)) + 1;
    b->h = max(get_h(b->left), get_h(b->right)) + 1;
    return b;
}
Tree * L_R(Tree *rt){
    Tree *a = rt;
    Tree *b = a->left;
    Tree *c = b->right;

    b->right = c->left;
    a->left = c->right;
    c->left = b;
    c->right = a;

    a->h = max(get_h(a->left), get_h(a->right)) + 1;
    b->h = max(get_h(b->left), get_h(b->right)) + 1;
    c->h = max(get_h(c->left), get_h(c->right)) + 1;

    return c;
}
Tree * R_L(Tree *rt){
    Tree *a = rt;
    Tree *b = a->right;
    Tree *c = b->left;

    b->left = c->right;
    a->right = c->left;
    c->left = a;
    c->right = b;

    a->h = max(get_h(a->left), get_h(a->right)) + 1;
    b->h = max(get_h(b->left), get_h(b->right)) + 1;
    c->h = max(get_h(c->left), get_h(c->right)) + 1;

    return c;
}
void del_meo(Tree *rt){
    if(rt){
        del_meo(rt->left);
        del_meo(rt->right);
        delete rt;
    }
    return;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: 算法9-9~9-12是关于平衡二叉树的基本操作,包括插入、删除、旋转等操作。平衡二叉树是一种特殊的叉搜索树,它的左右子树高度差不超过1,可以保证树的高度始终在log(n)级别,从而保证了树的查找、插入、删除等操作的时间复杂度都是O(log(n))。 具体来说,算法9-9是平衡二叉树的插入操作,它首先按照叉搜索树的规则找到要插入的位置,然后通过旋转操作来保持平衡。算法9-10是平衡二叉树的删除操作,它也是通过旋转操作来保持平衡。算法9-11和9-12是平衡二叉树的旋转操作,包括左旋、右旋、左右旋和右左旋,这些操作可以使树重新达到平衡状态。 总之,平衡二叉树的基本操作是非常重要的,它们可以保证树的高度始终在log(n)级别,从而保证了树的查找、插入、删除等操作的时间复杂度都是O(log(n)),是一种非常高效的数据结构。 ### 回答2: 平衡二叉树是一种基于查找树的数据结构,其在插入和删除节点时会自动调整,以保持树的平衡性。平衡二叉树的常见有AVL树、红黑树等。本文主要介绍平衡二叉树的基本操作,包括插入、删除和查找。 9-9 插入操作 在平衡二叉树中插入一个节点的过程和在查找树中插入节点的过程类似。不同的是,在插入结束后,需要检查当前节点是否失去平衡并做出相应的调整。 在插入节点时,需要记录节点的高度(从叶节点到根节点的距离)。如果当前节点为空,则将新节点插入到该节点处并将高度设置为1;否则,比较新节点的值和当前节点的值,如果新节点的值小于当前节点的值,则将新节点插入到当前节点的左子树中并更新该节点的高度;如果新节点的值大于当前节点的值,则将新节点插入到当前节点的右子树中并更新该节点的高度。 插入结束后,需要检查当前节点是否失去平衡。我们可以用该节点的左子树高度和右子树高度之差来衡量它是否平衡。如果该节点的平衡因子大于1,则需要进行旋转操作,以恢复平衡。 9-10 删除操作 在平衡二叉树中删除一个节点需要分为以下三种情况: 1. 被删除的节点为叶子节点,直接删除即可。 2. 被删除的节点有一个子节点,将该子节点代替被删除的节点即可。 3. 被删除的节点有两个子节点,需要找到它的中序遍历下一个节点(即比它大的最小节点)代替被删除的节点。如果该节点有右子树,则中序遍历下一个节点为右子树中最小的节点;如果该节点没有右子树,则中序遍历下一个节点为它的某个祖先节点。 删除结束后,需要检查当前节点是否失去平衡。如果失去平衡,则需要进行旋转操作,以恢复平衡。 9-11 查找操作 在平衡二叉树查找一个节点的过程和在查找树中查找节点的过程类似。需要从根节点开始,比较查找的值和当前节点的值。如果查找的值小于当前节点的值,则在左子树中递归查找;如果查找的值大于当前节点的值,则在右子树中递归查找;如果查找的值等于当前节点的值,则返回该节点。 9-12 平衡因子 平衡二叉树的平衡因子定义为当前节点的左子树高度和右子树高度之差。如果平衡因子的绝对值大于1,则说明该节点失去了平衡。在平衡二叉树中,每个节点的平衡因子只能为-1、0或1。如果不是这三个值,则需要进行旋转操作以恢复平衡。 ### 回答3: 平衡二叉树是一种特殊的叉搜索树,它的左右子树高度差不超过1。由于平衡二叉树对于插入、删除、查找等操作的时间复杂度都是O(logn),因此在许多应用场景中得到了广泛的应用。平衡二叉树的基本操作包括插入、删除、查找等,以下分别介绍: 9-9 插入操作:平衡二叉树的插入操作与普通叉搜索树相同,只是插入后需要进行平衡处理,避免出现左右子树高度差不平衡的情况。例如插入节点x,需要先查找其应当插入的位置,然后通过旋转操作将其父节点与祖父节点一起旋转,使得树重新平衡。插入操作的时间复杂度为O(logn)。 9-10 删除操作:删除操作也类似于普通叉搜索树,需要删除节点x后通过旋转操作迭代处理其祖先节点的平衡性,保证整个树的平衡性。删除操作的时间复杂度为O(logn)。 9-11 查找操作:查找操作与普通叉搜索树相同,只是由于平衡二叉树的高度比较平衡,因此可以保证其查找效率较高。查找操作的时间复杂度为O(logn)。 9-12 平衡操作:平衡二叉树的平衡操作主要包括旋转操作和重构操作。旋转操作通过将子树旋转到左右子树高度相等来实现平衡,分为左旋和右旋两种。重构操作通过重新构建平衡二叉树的结构来保证整个树的平衡性。平衡操作的时间复杂度为O(1)。 综上所述,平衡二叉树是一种高效的数据结构,其插入、删除、查找等基本操作时间复杂度都为O(logn),通过平衡操作可以保证整个树的平衡性。在实际应用中,平衡二叉树被广泛应用于数据库、搜索引擎、红黑树等场景中,具有重要的实用价值。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

leoxry

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值