Bootstrap

4 二叉树(Binary-Tree)与经典问题——C++&python刷算法

文章目录

1.二叉树相关基础知识

1.1 基础知识

在这里插入图片描述

基本概念:

  • 0.二叉树的度是“出度“ 即箭头朝外的
    在这里插入图片描述

  • 1.树的每个节点都有唯一的父节点

  • 2.每个节点的度最多为2

  • 3.度为0的节点比度为2的节点多1个

  • 4.n节点的树 有n-1条边

证明3——
n节点的树 有n-1条边
所以 节点数 = 边数+1
即为:
n0+n1+n2 (点数)= n1+2*n2+1(边数+1)
=====>n0 = n2 + 1 得证

1.2 二叉树的三种遍历方式

在这里插入图片描述

  • 前序遍历
    1 245 36

  • 中序遍历
    425 1 36
    在这里插入图片描述

  • 后序遍历
    452 63 1
    在这里插入图片描述

用这三个遍历能干啥?

拿着中序遍历的结果+前序/后序遍历的结果——
可以还原一棵二叉树

【1】先找到根节点
【2】拆出来 左子树中序遍历 左前 右中 右前
【3】再分别还原左子树 右子树

根据前序遍历和中序遍历结果 获得二叉树

在这里插入图片描述
前序 1 5 234
中序 5 1 324
在这里插入图片描述
在这里插入图片描述

前序 1 2 4 9 5 6 10 3 7 8
中序 4 9 2 10 6 5 1 3 8 7
【1】
在这里插入图片描述
【2】
在这里插入图片描述

【3】
在这里插入图片描述

在这里插入图片描述

1.3 特殊二叉树的性质

完全二叉树

可以使用连续的空间进行存储(数组)
在这里插入图片描述
没有度为1的节点,且所有度为0的叶子节点都在同一层

编号为i的子节点:
在这里插入图片描述

在完全二叉树中不需要记录子树的地址!
节省大量存储空间!!!!!

计算式和记录式

计算式节省空间——时间换空间

“需要节约空间一点的应用”——用计算式!

纪录是节省时间——空间换时间

数据结构改变的是我们思考问题的方法

培养数据结构思维!

满二叉树

没有(出)度为1 的 节点

1.4 关于树结构的深入理解

树的节点——代表集合
边——代表关系

2.学习二叉树的作用

2.1 学习二叉树的两大作用

作用一 理解 高级数据结构的基础

在这里插入图片描述
完全二叉树:

多叉树/森林:

二叉排序树:

  • 红黑树 一类非常重要的二叉排序树
  • B-(杠)树 B+树:文件系统 数据库 底层重要的数据结构

作用二 练习递归技巧的最佳选择

递归是空间换时间哦~

[重点思想]如何设计/理解递归程序?
  1. 数学归纳法——结构归纳法

  2. 赋予递归函数一个明确的意义
    在这里插入图片描述

  3. 思考边界条件

  4. 实现递归过程
    在这里插入图片描述

数学归纳法回顾
k0正确 假设ki是正确的 假设k(i+1)也是正确的
在这里插入图片描述

作用三 左孩子右兄弟表示法节省空间

把三叉树变为二叉树
在这里插入图片描述

为啥转化成二叉树要省空间啊?

举个栗子——

三叉树中每个节点存储3个指针域
有效指针域——指向明确节点的
在这里插入图片描述
例如这个三叉树 有6
3个指针域 其中有效指针域(具体的边)只有5个 浪费了13个指针域

而二叉树
在这里插入图片描述
6*2个指针域-5个有效指针域
浪费了7个
二叉树比三叉树香!

其中k元n叉树中的k和n越大 转换成二叉树越省空间!
n元k叉树浪费的空间——kn -(n-1)
n元2叉树浪费的空间——2n - (n-1)

**顺序存储结构和链式存储结构在二叉树上的优劣性

顺序:比较浪费空间(非完全二叉树时) 进行修改比较困难
读取某个结点的时候效率比较高

链式:空间占用小 容易修改
读取某个指定节点的时候效率偏低O(nlogn)

树形结构基本都是使用链式结构来进行存储

3.经典面试题-二叉树的基本操作

3.1 LC144 二叉树的前序遍历

LC144 二叉树的前序遍历
本人写的解题笔记


class Solution {
   
public:
	void preorder(TreeNode *root,vector<int> &res) {
   
		if (root == NULL) return; 
		//如果碰到空节点 递归终止 
		
		//递归出口是必要的! 
		
		res.push_back(root->val); //将根节点值放到结果数组中 
		//res.push_back(xxx) 在数组res的末尾插入元素xxx 
		
		preorder(root->left,res); // 递归左子树 
		//递归的作用——把遍历到的那个root->val插入res的末尾 
		
		preorder(root->right,res); // 递归右子树 
		return; 
	
;