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

算法与数据结构之二叉树(Binary Tree)


一、什么是二叉树(Binary Tree)

定义:

二叉树是一种树形结构,其中每个节点最多有两个子节点,分别称为左子节点(left child)右子节点(right child)

每个节点最多有 2 个分支,这两个分支可以为空。


例子

        A/ \B   C/ \   \D   E   F
  • A 是根节点(Root)
  • B、C 是 A 的孩子(Child)
  • D、E、F 是叶子节点(Leaf)
  • B 的父节点是 A
  • D 的兄弟节点是 E

二、二叉树的基本术语

名称含义
根节点(Root)没有父节点的节点
叶子节点(Leaf)没有子节点的节点
父节点(Parent)有子节点的节点
子节点(Child)父节点的下属节点
兄弟节点(Sibling)具有相同父节点的节点
节点深度(Depth)从根到该节点的边数
节点高度(Height)从该节点到叶子的最长路径
层级(Level)节点的深度 + 1
满二叉树(Full Binary Tree)所有非叶子节点都有两个子节点
完全二叉树(Complete Binary Tree)除最后一层外,其他层节点全满,最后一层从左到右依次填充

三、二叉树的分类

类型定义
普通二叉树任意结构
满二叉树所有非叶节点都有两个孩子,叶子都在同一层
完全二叉树除最后一层外全满,最后一层从左向右填充
二叉搜索树(BST)左子树 < 根 < 右子树
平衡二叉树(AVL Tree)左右子树高度差 ≤ 1
红黑树(Red-Black Tree)一种自平衡二叉搜索树
线索二叉树(Threaded Binary Tree)用空指针指向前驱/后继节点以加速遍历

四、二叉树的性质

设二叉树中第 iii 层最多有 2i−12^{i-1}2i1 个节点:

  1. iii 层最多节点数:
    Ni=2i−1N_i = 2^{i-1} Ni=2i1

  2. 深度为 kkk 的二叉树最多节点数:
    Nmax⁡=2k−1N_{\max} = 2^k - 1 Nmax=2k1

  3. 具有 nnn 个节点的二叉树,高度至少为:
    hmin⁡=⌈log⁡2(n+1)⌉h_{\min} = \lceil \log_2(n + 1) \rceil hmin=log2(n+1)⌉

  4. 若叶子节点数为 n0n_0n0,度为 2 的节点数为 n2n_2n2,则:
    n0=n2+1n_0 = n_2 + 1 n0=n2+1


五、二叉树的存储方式

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

适用于 完全二叉树

设根节点下标为 1,则:

  • 左孩子:2*i
  • 右孩子:2*i + 1
  • 父节点:i / 2

例如:

        A(1)/   \B(2)     C(3)/ \     /
D(4) E(5) F(6)

数组存储:

[ _, A, B, C, D, E, F ]

2.链式存储(指针结构)

struct TreeNode {int val;TreeNode* left;TreeNode* right;TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
};

每个节点保存两个指针,分别指向左、右子节点。


六、二叉树的遍历(Traversal)

遍历是访问二叉树所有节点的过程。

1.深度优先遍历(DFS)

  • 前序遍历(Preorder):根 → 左 → 右
    顺序:Root, Left, Right

  • 中序遍历(Inorder):左 → 根 → 右
    顺序:Left, Root, Right

  • 后序遍历(Postorder):左 → 右 → 根
    顺序:Left, Right, Root


示例

        A/ \B   C/ \   \D   E   F
遍历类型结果顺序
前序A B D E C F
中序D B E A C F
后序D E B F C A

递归实现(以中序为例)

void inorder(TreeNode* root) {if (!root) return;inorder(root->left);cout << root->val << " ";inorder(root->right);
}

2.广度优先遍历(BFS)

层序遍历(Level Order Traversal)
利用队列(Queue)实现。

void levelOrder(TreeNode* root) {if (!root) return;queue<TreeNode*> q;q.push(root);while (!q.empty()) {TreeNode* node = q.front(); q.pop();cout << node->val << " ";if (node->left) q.push(node->left);if (node->right) q.push(node->right);}
}

结果:

A B C D E F

七、二叉树的应用

应用场景示例
表达式解析树编译器、计算器((a+b)*c
二叉搜索树 BST查找、排序
堆(Heap)优先队列(最小堆、最大堆)
哈夫曼树(Huffman Tree)数据压缩
决策树(Decision Tree)机器学习
KD 树 / Octree空间索引与点云处理

八、构建与销毁

TreeNode* buildTree() {TreeNode* root = new TreeNode(1);root->left = new TreeNode(2);root->right = new TreeNode(3);root->left->left = new TreeNode(4);root->left->right = new TreeNode(5);return root;
}void destroy(TreeNode* root) {if (!root) return;destroy(root->left);destroy(root->right);delete root;
}

九、复杂度与性能

操作平均复杂度最坏情况
插入O(log⁡n)O(\log n)O(logn)O(n)O(n)O(n)(链化)
删除O(log⁡n)O(\log n)O(logn)O(n)O(n)O(n)
查找O(log⁡n)O(\log n)O(logn)O(n)O(n)O(n)
遍历O(n)O(n)O(n)O(n)O(n)O(n)

为避免退化,可使用 AVL TreeRed-Black Tree


十、总结表

分类特点示例
普通二叉树任意结构一般树结构
满二叉树每个非叶子都有两个孩子理论分析
完全二叉树从左至右填满
二叉搜索树左 < 根 < 右查找树
平衡树高度差≤1AVL、红黑树
线索树空指针指向前驱/后继遍历优化

十一、 综合示例-二叉搜索树(BST)

下面实现l一个完整的 Binary Search Tree 类,包括:

  • 节点定义
  • 插入节点
  • 查找节点
  • 删除节点
  • 三种深度优先遍历(前序 / 中序 / 后序)
  • 层序遍历
  • 销毁树

1.数据结构定义

#include <iostream>
#include <queue>
using namespace std;// 二叉树节点定义
struct TreeNode {int val;TreeNode* left;TreeNode* right;TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
};

2.二叉搜索树类定义

class BinarySearchTree {
private:TreeNode* root;// 插入节点(递归)TreeNode* insert(TreeNode* node, int val) {if (!node) return new TreeNode(val);if (val < node->val) node->left = insert(node->left, val);else if (val > node->val) node->right = insert(node->right, val);return node;}// 查找节点(递归)bool search(TreeNode* node, int val) {if (!node) return false;if (val == node->val) return true;else if (val < node->val) return search(node->left, val);else return search(node->right, val);}// 找到最小值节点TreeNode* findMin(TreeNode* node) {while (node->left) node = node->left;return node;}// 删除节点TreeNode* remove(TreeNode* node, int val) {if (!node) return nullptr;if (val < node->val) node->left = remove(node->left, val);else if (val > node->val) node->right = remove(node->right, val);else {// 情况 1:无子节点if (!node->left && !node->right) {delete node;return nullptr;}// 情况 2:只有一个子节点else if (!node->left) {TreeNode* temp = node->right;delete node;return temp;} else if (!node->right) {TreeNode* temp = node->left;delete node;return temp;}// 情况 3:有两个子节点else {TreeNode* minNode = findMin(node->right);node->val = minNode->val;node->right = remove(node->right, minNode->val);}}return node;}// 遍历函数void preorder(TreeNode* node) {if (!node) return;cout << node->val << " ";preorder(node->left);preorder(node->right);}void inorder(TreeNode* node) {if (!node) return;inorder(node->left);cout << node->val << " ";inorder(node->right);}void postorder(TreeNode* node) {if (!node) return;postorder(node->left);postorder(node->right);cout << node->val << " ";}// 销毁整棵树void destroy(TreeNode* node) {if (!node) return;destroy(node->left);destroy(node->right);delete node;}public:BinarySearchTree() : root(nullptr) {}~BinarySearchTree() { destroy(root); }void insert(int val) { root = insert(root, val); }void remove(int val) { root = remove(root, val); }bool search(int val) { return search(root, val); }// 层序遍历void levelOrder() {if (!root) return;queue<TreeNode*> q;q.push(root);while (!q.empty()) {TreeNode* node = q.front(); q.pop();cout << node->val << " ";if (node->left) q.push(node->left);if (node->right) q.push(node->right);}}// 打印不同遍历结果void printOrders() {cout << "Preorder: "; preorder(root); cout << "\n";cout << "Inorder: "; inorder(root); cout << "\n";cout << "Postorder: "; postorder(root); cout << "\n";cout << "Level order: "; levelOrder(); cout << "\n";}
};

3.主程序示例

int main() {BinarySearchTree bst;// 插入节点bst.insert(50);bst.insert(30);bst.insert(70);bst.insert(20);bst.insert(40);bst.insert(60);bst.insert(80);cout << "Binary Search Tree traversals:\n";bst.printOrders();cout << "\nSearch for 60: " << (bst.search(60) ? "Found" : "Not Found") << "\n";cout << "\nRemove 70\n";bst.remove(70);cout << "After deletion:\n";bst.printOrders();return 0;
}

输出结果

Binary Search Tree traversals:
Preorder: 50 30 20 40 70 60 80
Inorder: 20 30 40 50 60 70 80
Postorder: 20 40 30 60 80 70 50
Level order: 50 30 70 20 40 60 80Search for 60: FoundRemove 70
After deletion:
Preorder: 50 30 20 40 80 60
Inorder: 20 30 40 50 60 80
Postorder: 20 40 30 60 80 50
Level order: 50 30 80 20 40 60

示例分析

操作说明
插入构建一棵 BST,左小右大
查找二分性质快速定位
删除三种情况(无子、单子、双子)
遍历四种遍历全面展示树结构
销毁递归释放所有节点,避免内存泄漏

http://www.dtcms.com/a/606897.html

相关文章:

  • 算法笔记 11
  • 网站开发技术考题如何学建设网站
  • 沧浪苏州网站建设阿里巴巴网站怎么做推广
  • 论坛类网站搭建crm客户管理系统免费
  • 11.Fule安装OpenStack
  • 建设一个门户网站价格做长图的网站
  • 网站建设 前后台目录结构模板网页文档的默认扩展名为
  • 做企业网站一般用什么服务器黑龙江做网站的
  • php网站开发pdf亚马逊官方网站的建设
  • redis清理缓存
  • 门户网站建设要点wordpress 首页 函数
  • 0 基础入门爬虫:Python+requests 环境搭建保姆级教程
  • 网站移动端是什么问题个人网上注册公司入口
  • 扫地机如何高效的实现轨迹
  • 四川网站建设设计公司排名网站托管费用 优帮云
  • 亚马逊玩具合规新规深度解析:跨境卖家成本控制与合规落地指南
  • 本地服务网站开发惠州市 网站开发公司
  • 淘宝网站建设教程视频教程潍坊网站开发招生信息
  • 网站建设j介绍ppt电子游戏设计方案
  • iOS在制作framework时,oc与swift混编的流程及坑点!
  • 使用wrangler发布cf的workers项目
  • 如东网站制作网站建设工具哪家好
  • 零知IDE——基于STM32F103RBT6和SHT40温湿度传感器的环境监测系统
  • 建立手机个人网站福田企业网站优化有用吗
  • C语言反编译 | 如何高效实现C语言程序反编译及相关技术解析
  • 佛山网站建设过程做游乐设施模型的网站
  • 网站建设培训珠海招商广告
  • nginx wordpress 目录 伪静态seo北京公司
  • C++ 三分查找:在单调与凸函数中高效定位极值的算法
  • wordpress建站教程 cms浙江信息港