如何使用C语言实现平衡二叉树数据结构算法

使用C语言实现平衡二叉树数据结构算法可以分为以下几个步骤:

第一步:了解平衡二叉树

平衡二叉树是一种二叉搜索树,它具有以下特点:

  • 高度平衡:每个节点的左右子树的高度差不能超过1。
  • 有序性:对于任意一个节点,它的左子树中的所有节点都小于它,它的右子树中的所有节点都大于它。

平衡二叉树的优点在于它的查找、插入和删除操作都可以在O(log n)的时间内完成,比较快速。常见的平衡二叉树有红黑树和AVL树。

第二步:实现数据结构

要实现平衡二叉树,需要先定义数据结构。一个平衡二叉树节点应该包含以下信息:

  • 节点值 val
  • 左右子树指针 left 和 right
  • 节点高度 height

定义节点结构体:

typedef struct node {
    int val;
    struct node *left;
    struct node *right;
    int height;
} Node;

然后定义插入、删除等操作。以下是AVL树的实现代码。

插入操作

首先,需要定义计算节点高度的函数:

int height(Node *node) {
    if (!node)
        return 0;
    return node->height;
}

然后,可以写出插入节点的函数。当插入一个节点时,需要更新整棵树的高度和平衡因子。若某个节点的平衡因子超过 1 或小于 -1,则可能不在平衡状态,需要进行旋转操作。

int balanceFactor(Node *node) {
    return height(node->left) - height(node->right);
}

Node* rightRotate(Node *y) {
    Node *x = y->left;
    Node *T2 = x->right;

    x->right = y;
    y->left = T2;

    y->height = max(height(y->left), height(y->right)) + 1;
    x->height = max(height(x->left), height(x->right)) + 1;

    return x;
}

Node* leftRotate(Node *x) {
    Node *y = x->right;
    Node *T2 = y->left;

    y->left = x;
    x->right = T2;

    x->height = max(height(x->left), height(x->right)) + 1;
    y->height = max(height(y->left), height(y->right)) + 1;

    return y;
}

Node* insert(Node *node, int val) {
    if (!node) {
        Node *new = (Node *)malloc(sizeof(Node));
        new->val = val;
        new->left = NULL;
        new->right = NULL;
        new->height = 1;
        return new;
    }

    if (val < node->val) {
        node->left = insert(node->left, val);
    } else if (val > node->val) {
        node->right = insert(node->right, val);
    } else {
        return node;
    }

    node->height = max(height(node->left), height(node->right)) + 1;

    int bf = balanceFactor(node);

    if (bf > 1 && val < node->left->val) {
        return rightRotate(node);
    }

    if (bf < -1 && val > node->right->val) {
        return leftRotate(node);
    }

    if (bf > 1 && val > node->left->val) {
        node->left = leftRotate(node->left);
        return rightRotate(node);
    }

    if (bf < -1 && val < node->right->val) {
        node->right = rightRotate(node->right);
        return leftRotate(node);
    }

    return node;
}

删除操作

删除节点时,需要在树中找到对应的节点,然后对其进行删除操作。当一个或多个节点被删除时,可能会破坏树的平衡状态,需要进行平衡操作来保证树的平衡性。

Node* minValueNode(Node *node) {
    Node *cur = node;
    while (cur->left) {
        cur = cur->left;
    }
    return cur;
}

Node* deleteNode(Node *node, int val) {
    if (!node) {
        return node;
    }

    if (val < node->val) {
        node->left = deleteNode(node->left, val);
    } else if (val > node->val) {
        node->right = deleteNode(node->right, val);
    } else {
        if (!node->left || !node->right) {
            Node *temp = node->left ? node->left : node->right;

            if (!temp) {
                temp = node;
                node = NULL;
            } else {
                *node = *temp;
            }

            free(temp);
        } else {
            Node *temp = minValueNode(node->right);
            node->val = temp->val;
            node->right = deleteNode(node->right, temp->val);
        }
    }

    if (!node) {
        return node;
    }

    node->height = max(height(node->left), height(node->right)) + 1;

    int bf = balanceFactor(node);

    if (bf > 1 && balanceFactor(node->left) >= 0) {
        return rightRotate(node);
    }

    if (bf > 1 && balanceFactor(node->left) < 0) {
        node->left = leftRotate(node->left);
        return rightRotate(node);
    }

    if (bf < -1 && balanceFactor(node->right) <= 0) {
        return leftRotate(node);
    }

    if (bf < -1 && balanceFactor(node->right) > 0) {
        node->right = rightRotate(node->right);
        return leftRotate(node);
    }

    return node;
}

第三步:测试代码

为了验证实现是否正确,需要编写测试代码。以下是两个测试样例:

插入元素

int main() {
    Node *root = NULL;

    root = insert(root, 10);
    root = insert(root, 20);
    root = insert(root, 30);
    root = insert(root, 40);
    root = insert(root, 50);
    root = insert(root, 25);

    printf("Inorder traversal of the constructed AVL tree is: \n");
    inorder(root);

    root = deleteNode(root, 50);

    printf("\nInorder traversal of the AVL tree after deletion of 50 is: \n");
    inorder(root);

    return 0;
}

输出:

Inorder traversal of the constructed AVL tree is:
10 20 25 30 40 50
Inorder traversal of the AVL tree after deletion of 50 is:
10 20 25 30 40

删除元素

int main() {
    Node *root = NULL;

    root = insert(root, 9);
    root = insert(root, 5);
    root = insert(root, 10);
    root = insert(root, 0);
    root = insert(root, 6);
    root = insert(root, 11);
    root = insert(root, -1);
    root = insert(root, 1);
    root = insert(root, 2);

    /*
                9
               / \
              1  10
            /  \   \
           0    5   11
           /    / \
         -1    2   6
    */

    printf("Preorder traversal of the constructed AVL tree is \n");
    preorder(root);

    root = deleteNode(root, 10);

    /*
               1
              / \
             0   9
            /   / \
          -1   5   11
              / \
             2   6
    */

    printf("\nPreorder traversal after deletion of 10 \n");
    preorder(root);

    return 0;
}

输出:

Preorder traversal of the constructed AVL tree is
1 0 -1 9 5 2 6 10 11
Preorder traversal after deletion of 10
1 0 -1 5 2 6 9 11

到此为止,就完成了使用C语言实现平衡二叉树数据结构算法的完整攻略。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:如何使用C语言实现平衡二叉树数据结构算法 - Python技术站

(0)
上一篇 2023年5月17日
下一篇 2023年5月17日

相关文章

  • Halcon学习教程(一) 之提取十字线中心 图像分割

      原文作者:aircraft   原文链接:https://www.cnblogs.com/DOMLX/p/17266405.html      废话不多说,因为毕业后工作原因比较忙,好久没更新博客了,直接上图。。。     上图有个十字线,我们要提取出十字线的中心(Hhhh这个线是我随手画的 没画直!!) 第一步:肯定是读取图像进行灰度提取处理啦。   …

    算法与数据结构 2023年4月18日
    00
  • Go 语言数据结构之双链表学习教程

    Go 语言数据结构之双链表学习教程 一、前言 双链表是常见的数据结构,Go语言作为一种静态类型的语言,自带指针类型支持,因此在实现双链表时相对比较容易。本文中,我们将介绍双链表的基础理论和实践应用,并结合代码实现来详细讲解。 二、实现双链表的基本操作 1. 创建双链表 创建双链表需要定义链表中存储的元素类型,以及定义一个结构体来表示双链表中的一个节点。 ty…

    数据结构 2023年5月17日
    00
  • 稀疏数组

    引入 当在网页上下棋类游戏时,玩到中途想要离开,但是我们需要保存进度,方便下次继续 我们应该怎么实现 ? 以围棋举例 使用二维数组将棋盘记下 ,如 0 为 没有棋子 ,1 为 黑子 , 2为白子 但是没有棋子的地方都为 0 ,整个二维数组充斥着大量的无效数据 0 我们需要想一个办法来 优化存储的方式 基本介绍 当一个数组中大部分元素是同一个值时,我们可以使用…

    算法与数据结构 2023年4月25日
    00
  • Mysql 数据库结构及索引类型

    好的。首先,我们需要了解 Mysql 数据库的基本结构和索引类型。 Mysql 数据库结构 Mysql 数据库包含多个数据库,每个数据库包含多个数据表,每个数据表包含多个数据记录(或者叫行)。关键的概念包括数据库、数据表、数据记录以及 Mysql 列类型等。 数据库 Mysql 数据库是一个命名的容器,用于存储和管理相关数据表。可以使用以下 SQL 代码来创…

    数据结构 2023年5月17日
    00
  • Java数据结构之AC自动机算法的实现

    Java数据结构之AC自动机算法的实现 本文将详细讲解AC自动机算法在Java中的实现方法和原理,同时提供两个示例进行说明,使读者能够深入了解该算法并学会如何使用。 什么是AC自动机算法 AC自动机(Aho-Corasick Automaton)是多模式匹配的一种经典算法,其基本思路是将多个模式串构建成一颗“字典树”,然后对输入的文本串进行扫描匹配。相比于简…

    数据结构 2023年5月17日
    00
  • 深入解析MySQL索引数据结构

    深入解析MySQL索引数据结构 MySQL索引是优化查询效率的重要一环,本文将深入解析MySQL索引数据结构,帮助读者理解MySQL索引原理,并通过两个示例说明不同类型的索引在实际应用中的效果。 索引数据结构 MySQL支持两种类型的索引数据结构:B-Tree索引和Hash索引。 B-Tree索引 B-Tree索引是MySQL常用的索引类型,用于优化WHER…

    数据结构 2023年5月17日
    00
  • 使用JavaScript实现链表的数据结构的代码

    要使用JavaScript实现链表数据结构,需要考虑以下几个方面: 链表的基本结构 链表的基本操作(插入、删除、遍历等) JavaScript 实现数据结构的具体步骤 下面我将逐一阐述。 链表的基本结构 链表是由一系列节点所组成的数据结构,每个节点都保存着下一个节点的引用关系。链表可以是单向的,也可以是双向的。单向链表的节点只有指向下一个节点的指针,而双向链…

    数据结构 2023年5月17日
    00
  • Java红黑树的数据结构与算法解析

    Java红黑树的数据结构与算法解析 红黑树简介 红黑树是一种平衡二叉搜索树,其中的每个节点上都有一个黑色或红色的标记,并且满足以下性质: 根节点是黑色的; 叶子节点是黑色的空节点(NULL); 如果一个节点是红色的,则其子节点必须是黑色的; 从一个节点到该节点的子孙节点的所有路径上包含相同数目的黑节点; 新插入的节点默认是红色的。 具体来说,只有在删除或者某…

    数据结构 2023年5月17日
    00
合作推广
合作推广
分享本页
返回顶部