二叉树原理及其C语言实现

server/2025/2/6 8:30:37/

目录

二叉树原理

 应用场景

C语言实现

总结

扩展:平衡二叉树(AVL 树)


二叉树原理

二叉树是一种 非线性数据结构,是数据结构中的核心构造,每个节点最多有两个子节点,通常被称为左子节点(left subtree)和右子节点(right subtree)。以下是基于图形化的方式详细讲述的二叉树原理:

  1. 基本结构

    • 节点:包含一个数据元素及若干指向子树的分支。
    • 左子树和右子树:每个节点最多有两个子树,分别称为左子树和右子树,且左右之分次序不能颠倒。

结构示例

        A        ← 根节点/ \B   C      ← A的子节点/ \   \D   E   F    ← B和C的子节点
  • 根节点(Root):顶层的唯一节点(如 A)。

  • 叶子节点(Leaf):没有子节点的节点(如 D、E、F)。

  • 子树(Subtree):每个节点的左/右子节点构成的树(如 B 的子树是 D 和 E)。

  1. 类型

    • 普通二叉树:每个节点最多拥有两个子节点,树形结构没有强制约束。
    • 满二叉树:每个非叶子节点恰好具有两个子节点,且所有叶子节点位于同一层。
    • 完全二叉树:节点在层次结构上紧凑排列,最底层可能存在未满的节点,但这些节点一定从左到右依次填充。
    • 二叉查找树(BST):满足节点排序性质的二叉树,对任意节点,左子树的所有节点值均小于该节点,右子树的所有节点值均大于该节点。
    • 平衡二叉树:在BST的基础上增加平衡约束,使得树的任意左右子树高度差至多为1。常见的平衡树包括AVL树和红黑树。
  2. 性质

    • 在非空二叉树中,第i层的节点总数不超过2^(i-1)。
    • 深度为h的二叉树最多有2^h-1个节点,最少有h个节点。
    • 对于任意一棵二叉树,如果其叶节点数为N0,而度数为2的节点总数为N2,则N0=N2+1。

 应用场景

二叉树在计算机科学和数据结构中有着广泛的应用,以下是其主要应用场景:

  1. 数据压缩

    • 哈夫曼树:一种带权路径长度最短的二叉树,广泛应用于数据压缩和编码。通过哈夫曼编码,可以为数据构建最优的前缀编码,从而有效减少数据的存储空间。在实际应用中,哈夫曼树是文本压缩算法中的重要组成部分,广泛用于PNG、ZIP等压缩格式中。
  2. 高效查找

    • 二叉查找树(BST):其有序性使得BST在查找、插入和删除操作上的时间复杂度在理想情况下为O(log n)。因此,BST常被用作高效的动态集合数据结构
    • 平衡二叉树:如AVL树和红黑树,通过旋转操作来保持高度平衡,在最坏情况下依然能维持O(log n)的查找、插入和删除效率。因此,平衡BST在数据库索引结构中被广泛采用,以确保访问性能的稳定性。
  3. 优先级队列

    • :一种特殊的完全二叉树,分为最大堆和最小堆。在最大堆中,每个节点的值大于或等于其子节点的值,因此可以快速获取最大值;反之,最小堆则用于获取最小值。堆通常用于实现优先级队列,具有较高的插入和删除效率,同时在排序算法中(如堆排序)也有应用。
  4. 区间查询和动态更新

    • 线段树:一种基于区间分割的二叉树结构,专门用于解决数组中的区间查询和动态更新问题。其时间复杂度为O(log n),能够有效处理诸如区间和、区间最值等频繁变化的区间操作。线段树通常用于需要高效管理和查询大规模数据的场景中,如计算机图形学中的渲染问题。
  5. 其他应用场景

    • B树和B+树:这两种树结构在数据库管理系统和文件系统的索引实现中均得到了广泛应用。B树是一种多路平衡搜索树,适合频繁的插入和删除操作;而B+树则对B树进行了优化,增加了叶节点的链表连接,使得范围查询更加高效。
    • 决策树:一种基于数据特征进行递归分裂的树形结构,用于分类和回归任务。决策树通过最大化信息增益或最小化基尼系数等准则进行节点划分,直观地对数据进行决策,是机器学习中监督学习的重要工具。

C语言实现

//1. 定义二叉树节点结构体
#include <stdio.h>
#include <stdlib.h>typedef struct TreeNode {int data;struct TreeNode* left;struct TreeNode* right;
} TreeNode;//2. 创建新节点
TreeNode* createNode(int data) {TreeNode* newNode = (TreeNode*)malloc(sizeof(TreeNode));if (!newNode) {printf("内存分配失败!\n");exit(1);}newNode->data = data;newNode->left = NULL;newNode->right = NULL;return newNode;
}//3. 插入节点(以二叉搜索树为例)
// 递归插入
TreeNode* insertNode(TreeNode* root, int data) {if (root == NULL) {return createNode(data);  // 创建新节点}if (data < root->data) {root->left = insertNode(root->left, data);  // 插入左子树} else if (data > root->data) {root->right = insertNode(root->right, data); // 插入右子树}return root;  // 返回当前节点(避免重复插入)
}//4. 查找节点
// 递归查找
TreeNode* searchNode(TreeNode* root, int data) {if (root == NULL || root->data == data) {return root;}if (data < root->data) {return searchNode(root->left, data);} else {return searchNode(root->right, data);}
}//5. 删除节点(分三种情况)
// 找到右子树的最小节点(用于替代被删除节点)
TreeNode* findMinNode(TreeNode* node) {while (node->left != NULL) {node = node->left;}return node;
}TreeNode* deleteNode(TreeNode* root, int data) {if (root == NULL) return root;if (data < root->data) {root->left = deleteNode(root->left, data);} else if (data > root->data) {root->right = deleteNode(root->right, data);} else {// Case 1: 无子节点 或 Case 2: 只有一个子节点if (root->left == NULL) {TreeNode* temp = root->right;free(root);return temp;} else if (root->right == NULL) {TreeNode* temp = root->left;free(root);return temp;}// Case 3: 有两个子节点 → 用右子树最小节点替代TreeNode* temp = findMinNode(root->right);root->data = temp->data;  // 复制数据root->right = deleteNode(root->right, temp->data); // 删除原最小节点}return root;
}//6. 修改节点值
void modifyNode(TreeNode* root, int oldData, int newData) {TreeNode* target = searchNode(root, oldData);if (target != NULL) {target->data = newData;} else {printf("未找到节点 %d\n", oldData);}
}//7. 遍历二叉树(递归实现)
// 前序遍历:根 → 左 → 右
void preOrderTraversal(TreeNode* root) {if (root != NULL) {printf("%d ", root->data);preOrderTraversal(root->left);preOrderTraversal(root->right);}
}// 中序遍历:左 → 根 → 右(BST 会按升序输出)
void inOrderTraversal(TreeNode* root) {if (root != NULL) {inOrderTraversal(root->left);printf("%d ", root->data);inOrderTraversal(root->right);}
}// 后序遍历:左 → 右 → 根
void postOrderTraversal(TreeNode* root) {if (root != NULL) {postOrderTraversal(root->left);postOrderTraversal(root->right);printf("%d ", root->data);}
}//应用示例:模拟文件系统目录树
int main() {TreeNode* root = NULL;// 插入节点(模拟创建目录)root = insertNode(root, 50);  // 根目录insertNode(root, 30);         // 子目录1insertNode(root, 70);         // 子目录2insertNode(root, 20);         // 子目录1的子目录insertNode(root, 40);         // 子目录1的另一个子目录insertNode(root, 60);         // 子目录2的子目录printf("前序遍历: ");preOrderTraversal(root);  // 输出: 50 30 20 40 70 60printf("\n中序遍历: ");inOrderTraversal(root);   // 输出: 20 30 40 50 60 70printf("\n后序遍历: ");postOrderTraversal(root); // 输出: 20 40 30 60 70 50// 删除节点(模拟删除子目录1)root = deleteNode(root, 30);printf("\n删除后中序遍历: ");inOrderTraversal(root);   // 输出: 20 40 50 60 70// 修改节点值modifyNode(root, 20, 25);printf("\n修改后中序遍历: ");inOrderTraversal(root);   // 输出: 25 40 50 60 70return 0;
}

总结

扩展:平衡二叉树(AVL 树)

若需保证高效操作,可引入 平衡二叉树,通过旋转操作保持树高平衡:

// AVL 树节点增加高度属性
typedef struct AVLNode {int data;int height;struct AVLNode* left;struct AVLNode* right;
} AVLNode;

每次插入/删除后检查平衡因子(左右子树高度差),若超过阈值则旋转调整。


http://www.ppmy.cn/server/165364.html

相关文章

CommonAPI学习笔记-2

一. 概述 ​ 这篇文章主要是想整理并且分析CommonAPI代码生成工具根据fidl和fdepl配置文件生成出来的代码的结构和作用。 二. fidl ​ 用户根据业务需求在fidl文件中定义业务服务接口的结构以及自定义数据类型&#xff0c;然后使用core生成工具传入fidl文件生成该fidl的核心…

限流策略实战指南:从算法选择到阈值设置,打造高可用系统

前言 本文将深入探讨常见的限流算法及其适用场景&#xff0c;并详细解析基于 QPS 的限流方案。从如何设置合理的限流阈值&#xff0c;到请求被限流后的处理策略。 常见的限流算法 漏桶 核心原理 请求以任意速率进桶&#xff0c;以 恒定速率 出桶。若桶满则丢弃或排队等待适…

pytorch实现文本摘要

人工智能例子汇总&#xff1a;AI常见的算法和例子-CSDN博客 import numpy as npfrom modelscope.hub.snapshot_download import snapshot_download from transformers import BertTokenizer, BertModel import torch# 下载模型到本地目录 model_dir snapshot_download(tians…

Java项目: 基于SpringBoot+mybatis+maven+mysql实现的疾病防控综合管理系统(含源码+数据库+毕业论文)

一、项目简介 本项目是一套基于SpringBootmybatismavenmysql实现的疾病防控综合管理系统 包含&#xff1a;项目源码、数据库脚本等&#xff0c;该项目附带全部源码可作为毕设使用。 项目都经过严格调试&#xff0c;eclipse或者idea 确保可以运行&#xff01; 该系统功能完善、…

DeepSeek R1 Ascend全国产化大模型推理本地化部署教程它来了

DeepSeekR1在昇腾Atlas300IPro使用mindie推理套件在本地化部署大模型推理 更详细的mindie使用指导可参考这篇文章mindie官方指导文档 年前、年后deepseek火了一把&#xff0c;现在还是非常厉害。确实给Z国长脸了。现在也有很多客户想跑一跑deepseek R1以下我将基于华为的Mind…

高压GaN(氮化镓)器件在工业和汽车应用存在的致命弱点

高压GaN&#xff08;氮化镓&#xff09;器件在工业和汽车应用存在的致命弱点和被成熟低价的碳化硅MOSFET取代的原因。 高压GaN&#xff08;氮化镓&#xff09;器件虽然因其高电子迁移率、高击穿场强和高频特性备受青睐&#xff0c;但在大功率高压应用&#xff08;如电动汽车、光…

Ubuntu 16.04用APT安装MySQL

个人博客地址&#xff1a;Ubuntu 16.04用APT安装MySQL | 一张假钞的真实世界 安装MySQL 用以下命令安装MySQL: sudo apt-get install mysql-server 这个命令会安装MySQL服务器、客户端和公共文件。安装过程会出现两个要求输入的对话框&#xff1a; 输入MySQL root用户的密…

938. 二叉搜索树的范围和

二叉搜索树的范围和 给定二叉搜索树的根结点 root&#xff0c;返回值位于范围 [low, high] 之间的所有结点的值的和。 示例 1&#xff1a; 输入&#xff1a;root [10,5,15,3,7,null,18], low 7, high 15 输出&#xff1a;32 示例 2&#xff1a; 输入&#xff1a;root …