当前位置: 首页 > ds >正文

数据结构学习笔记 :树与二叉树详解

目录

  1. 树的基本概念
  2. 二叉树的定义与特性
  3. 二叉树的存储结构
    3.1 顺序存储
    3.2 链式存储
  4. 二叉树遍历
  5. 特殊二叉树类型
  6. 总结与应用场景

一、树的基本概念

核心定义

  • :由根节点和若干子树构成的层次结构。
  • 叶子节点(终端节点):没有子节点的节点。
  • 分支节点:有子节点的节点(根节点除外)。
  • 树的高度:节点所在层次的最大值。
  • 节点的度:子节点的数量;树的度:所有节点度的最大值。

树的性质

  1. 树中的结点数等于所有结点的度数之和加1。
  2. 度为m的树的第i层最多有m^(i-1)个节点。
  3. 满二叉树与完全二叉树的特殊性质(见后文)。

二、二叉树的定义与特性

二叉树的定义

  • 二叉树:每个节点最多有两个子节点(左子树和右子树)。
  • 五种形态
    1. 空树;
    2. 只有根节点;
    3. 根节点+左子树;
    4. 根节点+右子树;
    5. 根节点+左子树+右子树。

三、二叉树的存储结构

1. 顺序存储(数组实现)

#include <stdio.h>
#include <stdbool.h>
#define MaxSize 100
typedef int ElemType;typedef struct Tree {ElemType data[MaxSize]; // 数据域bool flag[MaxSize];     // 标记节点是否有效
} Tree;// 初始化
void InitTree(Tree *t) {for (int i = 0; i < MaxSize; i++) {t->flag[i] = false;}
}// 插入节点(构建二叉排序树)
bool insert_node(Tree *t, ElemType e) {int i = 1;while (i < MaxSize) {if (t->flag[i]) {if (t->data[i] >= e) {i = 2 * i; // 左子树方向} else {i = 2 * i + 1; // 右子树方向}} else {t->flag[i] = true;t->data[i] = e;return true;}}return false;
}// 查找节点
int find_tree(Tree *t, ElemType e) {int i = 1;while (i <= MaxSize) {if (t->flag[i]) {if (t->data[i] > e) {i = 2 * i; // 左子树方向} else if (t->data[i] < e) {i = 2 * i + 1; // 右子树方向} else {return i; // 找到返回编号}} else {return -1; // 未找到}}return -1;
}

2. 链式存储(动态节点)

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
typedef int ElemType;typedef struct BitNode {ElemType data;struct BitNode *lchild, *rchild;
} BitNode, *BitTree;// 新建节点
BitNode* newnode(ElemType e) {BitNode* node = (BitNode*)malloc(sizeof(BitNode));if (!node) return NULL;node->data = e;node->lchild = node->rchild = NULL;return node;
}// 插入节点(构建二叉排序树)
bool insert_node(BitTree *t, BitNode *new) {if (*t == NULL) { // 空树插入根节点*t = new;return true;}BitNode *p = *t;while (1) {if (new->data < p->data) { // 左子树方向if (p->lchild == NULL) {p->lchild = new;return true;}p = p->lchild;} else if (new->data > p->data) { // 右子树方向if (p->rchild == NULL) {p->rchild = new;return true;}p = p->rchild;} else {return false; // 数据重复}}
}

四、二叉树遍历

三种遍历方式

  1. 前序遍历(根左右)
void PreOrder(BitNode *root) {if (root == NULL) return;printf("%d ", root->data);PreOrder(root->lchild);PreOrder(root->rchild);
}
  1. 中序遍历(左根右)
void MidOrder(BitNode *root) {if (root == NULL) return;MidOrder(root->lchild);printf("%d ", root->data);MidOrder(root->rchild);
}
  1. 后序遍历(左右根)
void PostOrder(BitNode *root) {if (root == NULL) return;PostOrder(root->lchild);PostOrder(root->rchild);printf("%d ", root->data);
}

五、特殊二叉树类型

1. 满二叉树

  • 定义:高度为h的二叉树有2^h - 1个节点。
  • 特点
    • 除最后一层外,所有层的节点数达到最大。
    • 无度为1的节点。
    • 节点编号按层序从1开始,父节点i的左右子节点分别为2i2i+1

2. 完全二叉树

  • 定义:编号与满二叉树一致,即叶子节点仅出现在最后一层或倒数第二层。
  • 性质:可高效用数组存储。

3. 二叉排序树(BST)

  • 定义:左子树所有节点值 < 根节点值 < 右子树所有节点值。
  • 应用:快速搜索、插入和删除操作(平均时间复杂度O(log n))。

4. 平衡二叉树(AVL树)

  • 定义:所有节点的左右子树高度差≤1。
  • 作用:保证树的平衡性,避免退化为链表,确保操作效率。

六、总结与应用场景

核心总结

  1. 存储选择
    • 顺序存储:适合完全二叉树(如堆)。
    • 链式存储:通用,支持动态扩展。
  2. 遍历用途
    • 前序:复制二叉树。
    • 中序:对二叉排序树进行升序遍历。
    • 后序:释放内存、计算表达式。

典型应用场景

  • 二叉排序树:数据库索引、快速查找。
  • 平衡二叉树:需要高效插入/删除的场景(如动态数据集合)。
  • 堆(完全二叉树):优先队列实现。

希望这篇笔记能帮助读者掌握树与二叉树的核心概念及实现方法!

http://www.xdnf.cn/news/107.html

相关文章:

  • 学习threejs,使用EffectComposer后期处理组合器(采用RenderPass、GlitchPass渲染通道)
  • PyCharm入门导览
  • 蓝桥杯之前缀和
  • 基于单片机的温湿度采集系统(论文+源码)
  • 好数对的数目
  • 【系统分析师】-软件工程
  • 2025mathorcup妈妈杯数学建模挑战赛B 题:音智策引迁程,老城焕新颜,思路,模型,代码,持续更新中
  • 【文件操作与IO】详细解析文件操作与IO (一)
  • 15 nginx 中默认的 proxy_buffering 导致基于 http 的流式响应存在 buffer, 以 4kb 一批次返回
  • VUE3多国语言切换(国际化)
  • 数据结构初阶:二叉树(二)
  • 【MySQL数据库入门到精通】
  • 考研系列-计算机网络-第二章、物理层
  • C++_设计模式\_观察者模式(Observer Pattern)
  • .NET Core 服务实现监控可观测性最佳实践
  • 5.0.2 颜色16进制格式含义 控件template中path的使用
  • 微服务架构基础知识
  • ICPR-2025 | 让机器人在未知环境中 “听懂” 指令精准导航!VLTNet:基于视觉语言推理的零样本目标导航
  • 插入排序和希尔排序
  • R 语言科研绘图 --- 饼状图-汇总
  • 磁流变式汽车减振器创新设计与关键技术研究
  • OpenCV 中的分水岭算法的原理及其应用---图像分割的利器
  • 小红书爬虫,小红书api,小红书数据挖掘
  • 【go】什么是Go语言的GPM模型?工作流程?为什么Go语言中的GMP模型需要有P?
  • 【数据结构与算法】——插入排序
  • 深度监听 ref 和 reactive 的区别详解
  • python面向对象实现学员信息管理系统详解
  • 滑动窗口209. 长度最小的子数组
  • 如何避免被目标网站识别为爬虫?
  • 长亭2月公开赛Web-ssrfme