Balance Rotations of AVL Trees :AVL树的平衡

本文详细介绍了AVL树的实现,包括数据结构定义、插入操作以及四种旋转(左旋、右旋、左右旋、右左旋)的实现。通过插入节点并调整平衡因子,确保树的平衡,保持树的高度为O(logn)。程序清单展示了C语言的实现,并给出了测试样例及其输出,验证了AVL树的正确性。
摘要由CSDN通过智能技术生成

一、实验名称:Balance Rotations of AVL Trees

二、实验目的:

  1. 熟练掌握AVL树的数据结构,结构的特点;
  2. 能够实现AVL树的基本操作:如插入,调整,遍历,求树高等

三、实验内容:

An AVL tree is a binary search tree where every node in the tree has a balance factor of -1, 0 or +1. But any insertion into the AVL tree may cause violations of balance in four cases: Left-Left, Left-Right, Right-Right, and Right-Left. Single Rotations and Double Rotations are introduced to fix these cases.

  1. Determine the data structures for an AVL tree
  2. Implement an insertion into the AVL tree
  3. Implement the four possible rotations to fix violations of balance caused by the insertion.
    (End)

四. 程序清单(较为详细的注释):

#include <stdio.h>
#include <stdlib.h>
//在二叉树数据结构基础上添加高度成员.
struct ALVnode
{
    int val;
    struct ALVnode* left;
    struct ALVnode* right;
    int high;
};
typedef struct ALVnode* ALV;
int getHigh(ALV tree){
    if(!tree) return 0;
    int i=getHigh(tree->left);
    int j=getHigh(tree->right);
    return i>j?i+1:j+1;
}
/*将root与其左节点做左单旋(右转),因为root和其左节点的树高发生改变
,于是需要更新两者的高度,将根结点指向新的根节点(即左节点)并返回*/
ALV LeftLeft(ALV root){
    ALV temp=root;
    root=root->left;
    temp->left=root->right;
    root->right=temp;
    //更新树高
    temp->high=getHigh(temp);
    root->high=getHigh(root);
    return root;
}
/*将root与其右节点做右单旋(左转),因为root和其左节点的树高发生改变
,于是需要更新两者的高度,将根结点指向新的根节点(即右节点)并返回*/
ALV RightRight(ALV root){
    ALV temp=root;
    root=root->right;
    temp->right=root->left;
    root->left=temp;
    //更新树高
    temp->high=getHigh(temp);
    root->high=getHigh(root);
    return root;
}
/*将root的左子树进行右单旋可以使插入结点转移到左子树的左子树上,此时再进行root整体的左单旋*/
ALV LeftRight(ALV root){
    root->left=RightRight(root->left);
    root=LeftLeft(root);
    return root;
}
/*将root的右节点进行左单旋可以使插入结点转移到右子树的右子树上,此时再进行root整体的右单旋*/
ALV RightLeft(ALV root){
    root->right=LeftLeft(root->right);
    root=RightRight(root);
    return root;
}
ALV insert(ALV root,int val){
    if(root==NULL){//此时val是第一个数
        struct ALVnode*newNode=(struct ALVnode*)malloc(sizeof(struct ALVnode));
        newNode->val=val;
        newNode->high=1;
        newNode->left=NULL;
        newNode->right=NULL;
        root=newNode;//root指向新节点
    }
    else{
        //数值大于root的值插入到右边,小于插入到左边,等于插入无效(无法插入)
        if(val<root->val){
            root->left=insert(root->left,val);
            if((root->right==NULL&&root->left->high==2)||(root->right!=NULL&&root->left->high-root->right->high==2)){
                if(val<root->left->val)
                    root=LeftLeft(root);//左单旋
                else
                {
                    root=LeftRight(root);//左右双旋
                }
                
            }
        
        }
        else if(val>root->val){
            root->right=insert(root->right,val);
            if((root->left==NULL&&root->right->high==2)||(root->left!=NULL&&root->left->high-root->right->high==-2)){
                if(val<root->right->val)
                    root=RightLeft(root);//右左双旋
                else
                {
                    root=RightRight(root);//右单旋
                }
                
            }
        }
        //更新树高
        root->high=getHigh(root);
    }
    return root;
}
/*回收树的内存*/
void clear(ALV root){
    if(!root)return;
    clear(root->left);
    clear(root->right);
    free(root);
}
//以“结点值(左子树)(右子树)“的形式打印树,证明它是AVL树
void print(ALV root){
    if(!root)return;
    printf("%d",root->val);
    printf("(");
    print(root->left);
    printf(")");
    printf("(");
    print(root->right);
    printf(")");
}
int main(){
    int num;//要插入的结点数目
    ALV head=NULL;
    scanf("%d",&num);
    int temp;//用来存储要插入的数
    for(int  i=0;i<num;i++){
        scanf("%d",&temp);
        head=insert(head,temp);
    }
    //以“结点值(左子树)(右子树)“的形式打印树,证明它是AVL树
    print(head);
    clear(head);
    return 0;
}

五、测试结果:

输入输出格式说明:

  • 输入格式:
    先输入结点个数;
    依次输入顺序插入的结点值;

  • 输出格式:
    以“结点值(左子树)(右子树)“的形式打印树,证明它是AVL树

  • 测试样例1:

    输入:

    6
    1 2 3 4 5 6
    

    输出:

    4(2(1()())(3()()))(5()(6()()))
    
  • 测试样例2:

    输入:

    9
    33 22 11 44 55 6 43 22 11
    

    输出:

    22(11(6()())())(44(33()(43()()))(55()()))
    
  • 测试样例3:

    输入:

    7
    88 70 61 96 120 90 65
    

    输出:

    88(65(61()())(70()()))(96(90()())(120()()))
    
  • 测试样例4:

    输入:

    0
    

    输出:

  • 测试样例5:(随机数样例)

    输入:

    100
    1610 1280 299 53 1760 1677 149 1769 1325 1991 721 1451 2168 465 824 1517 1162 944 1782 69 1188 1112 16 148 1418 1429 1675 1232 2184 775 761 1714 13 623 1399 971 112 1299 1778 1819 1199 1463 924 603 356 1462 230 1828 320 2218 1429 24 1697 936 640 1462 1510 150 114 1101 206 194 357 1895 999 2082 15 320 2051 228 1325 216 741 1768 69 1311 1019 150 2190 824 210 790 788 2144 1039 1154 269 83 1521 491 1238 539 2007 1054 433 1186 855 1450 833 2049
    

    输出:

    1280(465(149(69(16(13()(15()()))(53(24()())()))(114(112(83()())())(148()())))(228(206(150()(194()()))(216(210()())()))(299(230()(269()()))(356(320()())(357()(433()()))))))(944(775(721(623(539(491()())(603()()))(640()()))(761(741()())()))(824(790(788()())())(924(855(833()())())(936()()))))(1101(1019(999(971()())())(1039()(1054()())))(1162(1112()(1154()()))(1199(1188(1186()())())(1232()(1238()())))))))(1677(1451(1325(1299()(1311()()))(1418(1399()())(1429()(1450()()))))(1517(1463(1462()())(1510()()))(1610(1521()())(1675()()))))(1782(1760(1714(1697()())())(1769(1768()())(1778()())))(2082(1991(1828(1819()())(1895()()))(2049(2007()())(2051()())))(2184(2168(2144()())())(2218(2190()())())))))
    

六、算法分析:

插入的时间复杂度为O(logn),空间复杂度为AVL树的内存和递归函数执行时候栈的内存。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在无人机飞行控制中,需要对无人机的姿态进行控制,其中包括对其飞行方向的控制。当无人机发生姿态变化时,需要对其姿态进行插值,以保证飞行过程中的平稳性和稳定性。 具体来说,插值姿态可以通过以下步骤实现: 1. 通过传感器获取当前无人机的姿态信息,包括欧拉角或四元数等。 2. 根据控制算法计算出目标姿态,即无人机需要达到的姿态。 3. 使用姿态插值算法,将当前姿态和目标姿态进行插值,得到中间姿态。 4. 将中间姿态作为控制指令发送给无人机进行控制。 在插值算法中,常用的方法是线性插值和球面线性插值。线性插值是指在两个姿态之间进行线性插值,即将两个姿态之间的欧拉角或四元数进行线性插值,从而得到中间姿态。而球面线性插值是指在欧几里得空间中进行插值,即在两个姿态之间的球面上进行插值,从而得到中间姿态。 在具体实现中,可以使用相应的数学库,如numpy、scipy等,来实现插值算法。下面是一个简单的Python示例代码,用于对无人机的姿态进行插值: ```python import numpy as np from scipy.spatial.transform import Rotation as R # 获取当前和目标姿态 current_orientation = R.from_euler('xyz', [0, 0, 0], degrees=True) target_orientation = R.from_euler('xyz', [45, 0, 0], degrees=True) # 计算插值步长 steps = 10 step_size = 1.0 / (steps - 1) # 进行姿态插值 interpolated_orientations = [] for i in range(steps): slerp = R.from_slerp(step_size * i, current_orientation, target_orientation) interpolated_orientations.append(slerp.as_euler('xyz', degrees=True)) ``` 在上述代码中,我们使用`scipy`库的`Rotation`模块获取了当前和目标姿态,然后计算了插值步长,并使用`from_slerp()`方法进行球面线性插值,得到了中间姿态。最后,我们将插值后的姿态保存在`interpolated_orientations`列表中,可用于控制无人机的姿态。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值