深入解析AVL树:高效实现二叉平衡搜索树(2)

本文涉及的产品
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云解析 DNS,旗舰版 1个月
简介: 深入解析AVL树:高效实现二叉平衡搜索树

深入解析AVL树:高效实现二叉平衡搜索树(1)https://developer.aliyun.com/article/1541698

4.右左双旋

先介绍右旋的实现

void right_rotate(node *up) {
    node *root = up->parent;
    node *down = up->right;
    if (down->left) {          // 右旋时处理子节点的左子节点
        up->right = down->left;
        down->left->parent = up;
    }
  // 调换上下位置
    down->left = up;     
    down->parent = root;
    up->parent = down;
    // height
    up->height = update_height(up);
    down->height = update_height(down); 
}

左旋和右旋的区别就在于,把上述代码的left和right字段调换位置

而左右和右左双旋就是进行两次旋转

因此,所有的旋转操作,只看这一段代码就够了,根据图示很好理解

修正代码:

void insert_fix(node *n) {
    while (n != tree->root) {
        update_height(n);
        int balance = get_balance(n);
        if (balance > 1) {
            if (get_balance(n->left) < 0) { // 考虑需要左右双旋的情况
                left_rotate(n->left);
            }
            right_rotate(n);
        } else if (balance < -1) {
            if (get_balance(n->right) > 0) { // 考虑右左双旋
                right_rotate(n->right);
            }
            left_rotate(n);
        }
        n = n->parent;
    }
}  

delete和insert的修正代码相同

修正逻辑如下:

1.从叶子节点开始判断平衡条件

2.对于不平衡的节点,根据get_balance的值判断需要左旋还是右旋

3.判断不平衡节点的子节点是否平衡,因为上一次旋转操作可能会造成其兄弟节点不平衡

完整代码
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#define MAX(a,b) (a > b) ? (a) : (b)
// 节点
typedef struct node {
    int key;
    int height;
    struct node *parent;
    struct node *left;
    struct node *right;
} node;
struct tree{
    node *root; 
    node *min;
    node *max;
};
struct tree *tree;
// 创建新节点
node* create_node(int k) {
    node* node = (struct node *)malloc(sizeof(struct node));
    if (!node) return NULL;
    node->key = k;
    node->parent = NULL;
    node->left = NULL;
    node->right = NULL;
    node->height = 1; // 默认最小高度为 1
    return node; 
}
#if 0
// 节点高度,递归
int height(node *n) {
    if (n == NULL) return 0;
    if (n->left == NULL && n->right == NULL) {
        return 1;
    } else {
        n->height = MAX(height(n->left), height(n->right)) + 1;
    }
    return n->height;
}
#endif
// 节点高度
int height(node *n) {
    return n ? n->height : 0;
}
// 更新节点高度
int update_height(node *n) {
    if (n != NULL) {
        n->height = MAX(height(n->left), height(n->right)) + 1;
    }
    return n->height;
}
node * find_min(node *root) {
    if (root == NULL) return root;
    node *cur = root;
    while (!(cur->left == NULL && cur->right == NULL)) {
        cur = cur->left;
    }
    return cur;
}
node * find_max(node *root) {
    if (root == NULL) return root;
    node *cur = root;
    while (!(cur->left == NULL && cur->right == NULL)) {
        cur = cur->right;
    }
    return cur;
}
node * find_root(node *n) {
    node *cur = n;
    while (cur->parent != NULL) {
        cur = cur->parent;
    }
    return cur;
}
// 左旋
void left_rotate(node *up) {
    node *root = up->parent;
    node *down = up->left; // left child
    if (down->right) {         // down's right will be up's left 
        up->left = down->right;
        down->right->parent = up;
    }
    down->right = up;
    down->parent = root;
    up->parent = down;
    // height
    up->height = update_height(up);
    down->height = update_height(down);
}
// 右旋
void right_rotate(node *up) {
    node *root = up->parent;
    node *down = up->right;
    if (down->left) {
        up->right = down->left;
        down->left->parent = up;
    }
    down->left = up;
    down->parent = root;
    up->parent = down;
    // height
    up->height = update_height(up);
    down->height = update_height(down); 
}
#if 0
int get_balance(node *n) {
    return n ? update_height(n->left) - update_height(n->right) : 0;
}
#endif
int get_balance(node *n) {  // 左右子节点高度差
    if (n == NULL) return 0;
    if (n->left == NULL && n->right == NULL) {
        return 0;
    } else if (n->left == NULL) {
        return update_height(n->right);
    } else if (n->right == NULL) {
        return update_height(n->left);
    }else {
        return update_height(n->left) - update_height(n->right);
    }
}
void insert_fix(node *n) {
    while (n != tree->root) {
        update_height(n);
        int balance = get_balance(n);
        if (balance > 1) {
            if (get_balance(n->left) < 0) { // 考虑需要右左双旋的情况
                right_rotate(n->left);
            }
            left_rotate(n);
        } else if (balance < -1) {
            if (get_balance(n->right) > 0) { // 考虑左右双旋 
                left_rotate(n->right);
            }
            right_rotate(n);
        }
        n = n->parent;
    }
}
void delete_fix(node *n) {
    while (n->parent != NULL) { //  根节点也要修正
        update_height(n);
        int balance = get_balance(n);
        if (balance > 1) {
            if (get_balance(n->left) < 0) { // 考虑需要右左双旋的情况
                right_rotate(n->left);
            }
            left_rotate(n);
        } else if (balance < -1) {
            if (get_balance(n->right) > 0) { // 考虑左右双旋
                left_rotate(n->right);
            }
            right_rotate(n);
        }
        n = n->parent;
    }
}
void insert(node *root, node *node) {
    if (node == NULL) return;
    if (root == NULL) {
        root = node;
        tree->root = node; // 更新全局 root
        tree->min = node;
        tree->max = node;
        return;
    }
    struct node *cur = root;
    int k = node->key;
    while (!(cur->left == NULL && cur->right == NULL)) {
        if (k <= cur->key) {
            cur = cur->left;
        } else {
            cur = cur->right;
        }
    }
    if (k <= cur->key) {
        cur->left = node;
        node->parent = cur;
    } else {
        cur->right = node;
        node->parent = cur;
    }
    insert_fix(node);
    tree->min = find_min(tree->root);
    tree->max = find_max(tree->root);
}
node* delete(node *root, node* n) {
    if (n == NULL) return NULL;
   
    node *temp;
    if (root == NULL) 
        printf("target is not found\n");
    else { 
        if (n->key < root->key)
            root->left = delete(root->left, n); // 在左子树递归查找删除
        else if (n->key > root->key)
            root->right = delete(root->right, n); // 在右子树递归查找删除
        else { // 删除当前根节点
            if (root->left && root->right) { // 被删除节点有左右两个子节点
                temp = find_min(root->right); // 用右子树的最小节点替换被删除节点
                root->key = temp->key; // 替换被删除节点
                root->right = delete(root->right, temp); // 删除用作替换的节点
            }
            else { // 被删除节点只有一个或无子节点
                temp = root;
                if (root->left == NULL) 
                    root = root->right;
                else
                    root = root->left;
                free (temp); // 被删除的节点
            }
        }
        
    }    
    update_height(root);
    delete_fix(find_min(tree->root));
    delete_fix(find_max(tree->root));
    tree->root = find_root(tree->root);
    update_height(tree->root);
    tree->min = find_min(tree->root);
    tree->max = find_max(tree->root);
    return root; // 删除后,返回根节点
}
node * search_node(int key) {
    node * temp = tree->root;
    while (!(temp->left == NULL && temp->right == NULL)) {
        if (key < temp->key)
            temp = temp->left;
        else if (key > temp->key)
            temp = temp->right;
        else 
            return temp;
    }
    return NULL;
}
int main() {
    tree = (struct tree *)malloc(sizeof(struct tree));
    memset(tree, 0, sizeof(*tree));
     // 测试代码
    int keys[] = {20, 4, 26, 3, 9, 15, 30};
    for (int i = 0; i < sizeof(keys) / sizeof(keys[0]); i++) {
        node *n = create_node(keys[i]);
        insert(tree->root, n);
    }
    printf("Root: %d\n", tree->root->key);
    printf("Min: %d\n", tree->min->key);
    printf("Max: %d\n", tree->max->key);
    // 删除节点
    delete(tree->root, search_node(9));
    printf("Root after deletion: %d\n", tree->root->key);
    printf("Min after deletion: %d\n", tree->min->key);
    printf("Max after deletion: %d\n", tree->max->key);
    // 清理树
    while (tree->root != NULL) {
        tree->root = delete(tree->root, tree->root);
    }
    free(tree);
    return 0;
}

推荐学习 https://xxetb.xetslk.com/s/p5Ibb

目录
相关文章
|
21天前
|
机器学习/深度学习 搜索推荐 API
淘宝/天猫按图搜索(拍立淘)API的深度解析与应用实践
在数字化时代,电商行业迅速发展,个性化、便捷性和高效性成为消费者新需求。淘宝/天猫推出的拍立淘API,利用图像识别技术,提供精准的购物搜索体验。本文深入探讨其原理、优势、应用场景及实现方法,助力电商技术和用户体验提升。
|
3天前
|
数据采集 XML 数据格式
解析Amazon搜索结果页面:使用BeautifulSoup
解析Amazon搜索结果页面:使用BeautifulSoup
|
3月前
|
存储 缓存 自然语言处理
深度解析ElasticSearch:构建高效搜索与分析的基石
【9月更文挑战第8天】在数据爆炸的时代,如何快速、准确地从海量数据中检索出有价值的信息成为了企业面临的重要挑战。ElasticSearch,作为一款基于Lucene的开源分布式搜索和分析引擎,凭借其强大的实时搜索、分析和扩展能力,成为了众多企业的首选。本文将深入解析ElasticSearch的核心原理、架构设计及优化实践,帮助读者全面理解这一强大的工具。
270 7
|
5月前
|
存储 弹性计算 应用服务中间件
阿里云经济型e与通用算力型u1实例长效特价云服务器解析,性能与性价比的完美平衡
阿里云目前有两款深受个人和普通企业用户喜欢的特价云服务器,ECS 经济型e实例2核2G,3M固定带宽,40G ESSD Entry云盘,仅需99元1年。ECS u1实例2核4G,5M固定带宽,80G ESSD Entry盘,仅需199元1年。新老同享,活动期间新购、续费同价。很多用户关心这两款云服务器性能怎么样?本文将对阿里云2024年推出的特价云服务器进行深度解析,从性能、价格、适用场景等多个维度进行详细探讨,以供选择参考。
阿里云经济型e与通用算力型u1实例长效特价云服务器解析,性能与性价比的完美平衡
|
5月前
|
算法 C++
【C++高阶】高效搜索的秘密:深入解析搜索二叉树
【C++高阶】高效搜索的秘密:深入解析搜索二叉树
50 2
|
5月前
|
人工智能 自然语言处理 搜索推荐
阿里云搜索开发工作台:快速搭建AI语义搜索与RAG链路的深度解析
阿里云搜索开发工作台凭借其丰富的组件化服务和强大的模型能力,为企业快速搭建AI语义搜索及RAG链路提供了有力支持。通过该平台,企业可以灵活调用各种服务,实现高效的数据处理、查询分析、索引构建和文本生成等操作,从而大幅提升信息获取与处理能力。随着AI技术的不断发展,阿里云搜索开发工作台将继续优化和完善其服务,为企业数字化转型和智能化升级注入更强动力。
181 0
|
6月前
|
存储
深入解析AVL树:高效实现二叉平衡搜索树
深入解析AVL树:高效实现二叉平衡搜索树
31 1
|
5月前
|
JavaScript
js 解析和操作树 —— 获取树的深度、提取并统计树的所有的节点和叶子节点、添加节点、修改节点、删除节点
js 解析和操作树 —— 获取树的深度、提取并统计树的所有的节点和叶子节点、添加节点、修改节点、删除节点
154 0
|
1月前
|
监控 Java 应用服务中间件
高级java面试---spring.factories文件的解析源码API机制
【11月更文挑战第20天】Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置、起步依赖和内嵌服务器等特性,极大地简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是spring.factories文件的解析源码API机制。
76 2
|
2天前
|
存储 设计模式 算法
【23种设计模式·全精解析 | 行为型模式篇】11种行为型模式的结构概述、案例实现、优缺点、扩展对比、使用场景、源码解析
行为型模式用于描述程序在运行时复杂的流程控制,即描述多个类或对象之间怎样相互协作共同完成单个对象都无法单独完成的任务,它涉及算法与对象间职责的分配。行为型模式分为类行为模式和对象行为模式,前者采用继承机制来在类间分派行为,后者采用组合或聚合在对象间分配行为。由于组合关系或聚合关系比继承关系耦合度低,满足“合成复用原则”,所以对象行为模式比类行为模式具有更大的灵活性。 行为型模式分为: • 模板方法模式 • 策略模式 • 命令模式 • 职责链模式 • 状态模式 • 观察者模式 • 中介者模式 • 迭代器模式 • 访问者模式 • 备忘录模式 • 解释器模式
【23种设计模式·全精解析 | 行为型模式篇】11种行为型模式的结构概述、案例实现、优缺点、扩展对比、使用场景、源码解析

热门文章

最新文章

推荐镜像

更多