前端学习记录
  • 前言及目录
  • 前端基础
    • HTML
    • CSS
      • CSS学习之布局
    • JavaScript
      • 跟着月影学JavaScript
      • JavaScript之对象、原型链及继承
      • JavaScript中的类
      • onclick与addEventListener区别
      • JS手撕题
    • HTTP与浏览器
      • HTTP实用指南
      • Web开发的安全之旅
    • 通用知识
      • 前端必须知道的开发调试知识
      • 前端设计模式应用
      • Web 标准与前端开发
  • 数据结构及算法
    • 数据结构
      • 1、线性表(List)
      • 2、堆栈(Stack)
      • 3、队列(Queue)
      • 4、二叉树(Binary Tree)
      • 5、二叉搜索树与平衡二叉树(BST & AVL)
      • 6、堆(Stack)& 哈夫曼树 & 并查集
      • 7、图(Graph)
        • 图论——解决最小生成树问题(Kruskal算法&Prim算法)
      • 8、排序(sort)
      • 9、散列表(hash)
      • 数据结构习题
        • 第一周:最大子列和算法、二分查找
        • 第二周:线性结构
        • 第三周:栽树(二叉树等)
        • 第四周:二叉搜索树&二叉平衡树
        • 第五周:堆&哈夫曼树&并查集
        • 第六周:图(上)连通集 、DFS&BFS
        • 第七周:图(中)Floyd算法求最短路
        • 第八周:图(下)
        • 第九周:排序(上)归并&堆排序
        • 第十周:排序(下)
        • 第十一周:散列查找 & KMP
    • CS基础
      • 编译原理 实验一 词法分析器设计
      • 编译原理 实验二 LL(1)分析法程序
    • LeetCode
      • 冲刺春招-精选笔面试 66 题大通关
        • day1:21. 合并两个有序链表、146. LRU 缓存、25. K 个一组翻转链表
        • day2:14. 最长公共前缀、3. 无重复字符的最长子串、124. 二叉树中的最大路径和
        • day3:206. 反转链表、199. 二叉树的右视图、bytedance-016最短移动距离
        • day4:1. 两数之和、15. 三数之和、42. 接雨水
        • day5:7. 整数反转、215. 数组中的第K个最大元素、23. 合并K个升序链表
        • day6:33. 搜索旋转排序数组、54. 螺旋矩阵、bytedance-006. 夏季特惠
        • day7:53. 最大子数组和、152. 乘积最大子数组、41. 缺失的第一个正数
        • day8:20. 有效的括号、200. 岛屿数量、76. 最小覆盖子串
        • day9:105. 从前序与中序遍历序列构造二叉树、103. 二叉树的锯齿形层序遍历、bytedance-010. 数组组成最大数
        • day10:94. 二叉树的中序遍历、102. 二叉树的层序遍历、394. 字符串解码
        • day11:415. 字符串相加、5. 最长回文子串、72. 编辑距离
        • day12:64. 最小路径和、300. 最长递增子序列、bytedance-004. 机器人跳跃问题
        • day13:88. 合并两个有序数组、31. 下一个排列、4. 寻找两个正序数组的中位数
        • day14:121. 买卖股票的最佳时机、56. 合并区间、135. 分发糖果
        • day15:232. 用栈实现队列、22. 括号生成、128. 最长连续序列
        • day16:bytedance-007. 化学公式解析、129. 求根节点到叶节点数字之和、239. 滑动窗口最大值
        • day17:141. 环形链表、236. 二叉树的最近公共祖先、92. 反转链表 II
        • day18:322. 零钱兑换、198. 打家劫舍、 bytedance-003. 古生物血缘远近判定
        • day19:160. 相交链表、143. 重排链表、142. 环形链表 II
        • day20:704. 二分查找、43. 字符串相乘、bytedance-002. 发下午茶
        • day21题目:69. x 的平方根、912. 排序数组、887. 鸡蛋掉落
        • day22:151. 颠倒字符串中的单词、46. 全排列、2. 两数相加
      • 剑指 Offer
        • 剑指offer day1 栈与队列(简单)
        • 剑指offer day2 链表(简单)
        • 剑指offer day3 字符串(简单)
        • 剑指offer day4 查找算法(简单)
        • 剑指offer day5 查找算法(中等)
        • 剑指offer day6 搜索与回溯算法(简单)
        • 剑指offer day7 搜索与回溯算法(简单)
        • 剑指offer day8 动态规划(简单)
        • 剑指offer day9 动态规划(中等)
        • 剑指offer day10 动态规划(中等)
        • 剑指offer day11 双指针(简单)
        • 剑指offer day12 双指针(简单)
        • 剑指offer day13 双指针(简单)
        • 剑指offer day14 搜索与回溯算法(中等)
        • 剑指offer day15 搜索与回溯算法(中等)
        • 剑指offer day16 排序(简单)
        • 剑指offer day17 排序(中等)
      • 剑指 Offer 专项突击版
  • 前端进阶
    • React
      • 响应式系统与 React
      • React学习小记
      • Redux学习之Redux三原则、createSore原理及实现
    • Vue
    • TypeScript
      • TypeScript入门
      • TypeScript 类型体操练习
        • Easy题(13/13)
        • Middle(20/72)
    • 前端工程化
      • Webpack知识体系
    • Node
    • 前端动画与绘图
      • WebGL基础
      • 前端动画简介
      • Floating UI 使用经验分享 - Popover
      • Floating UI 使用经验分享 - Dialog
      • Three.js 学习
        • 学习记录
        • 资源记录
    • 前端性能优化
    • 跨端
      • RN 学习小记之使用 Expo 创建项目
    • 开源
    • SEO 优化
      • 搜索引擎优化 (SEO) 新手指南笔记
  • 笔面试记录
    • 面经集锦
      • 2022春暑期实习MetaApp一二面面经
      • 2022春暑期实习字节前端一面凉经
    • 笔试复盘
      • 2022春暑期实习-美团前端-笔试
      • 2022春暑期实习-360前端-笔试(AK)
      • 2022春暑期实习-京东前端-笔试
      • 2022春暑期实习-网易雷火前端-笔试(AK)
      • 2022春暑期实习-网易互联网前端-暑期实习笔试
由 GitBook 提供支持
在本页
  • 一、什么是树
  • 二、树的表示
  • 三、二叉树

这有帮助吗?

在GitHub上编辑
导出为 PDF
  1. 数据结构及算法
  2. 数据结构

4、二叉树(Binary Tree)

上一页3、队列(Queue)下一页5、二叉搜索树与平衡二叉树(BST & AVL)

最后更新于3年前

这有帮助吗?

一、什么是树

1.树的定义

树(Tree):n(n≥0)个结点构成的有限集合。 当n=0时,称为空树; 对于任一棵非空树(n>0),它具备以下性质:

  1. 树中有一个称为“根(Root)”的特殊结点,用r表示。

  2. 其余结点可分为m(m>0)个互不相交的有限集T1,T2,……,Tm,其中每个集合本身又是一棵树,称为原来树的“子树(SubTree)”。

  3. 子树是不相交的

  4. 除了根结点外,每个结点有且仅有一个父结点;

  5. 一个N个结点的树有N-1条边。

2.树的一些基本术语

1. 结点的度(Degree): 结点拥有子结点的数量 2. 树的度: 最大的结点的度称为树的度 3. 叶结点(Leaf): 度为0的结点 4. 父结点(Parent): 如果有上一个结点,则称这个上一结点是它的父结点,如果没有上一结点,则这个属性则无父结点。 5. 子结点(Child): 若A结点是B结点的父结点,则称B结点是A结点的子结点;子节点也称孩子结点 6. 兄弟结点(Sibling): 具有同一父结点的各结点彼此是兄弟结点。 7. 路径和路径长度: 从结点n1到nk的路径为一个节点序列n1,n2,……,nk,ni是ni+1的父结点。路径所包含边的个数为路径的长度 8. 祖先结点(Ancestor): 沿树根到某一结点路径上的所有节点都是这个结点的祖先结点 9. 子孙结点(Descendant): 某一结点的子树中所有结点是这个结点的子孙 10. 结点的层次(Level): 规定根结点在1层,其它任一结点的层数是其父结点的层数加1。 11. 树的深度(Depth): 树中所有结点的最大层次是这棵树的深度。 12. 森林: m棵不相交的树的集合

二、树的表示

1.儿子-兄弟表示法

在这里插入图片描述
在这里插入图片描述

三、二叉树

1.定义

  1. Boolean IsEmpty(BinTree BT); //判别BT是否为空

  2. void Traversal(BinTree BT); //遍历,按某顺序访问某个结点;

  3. BinTree CreatBinTree(); //创建一个二叉树

常用的遍历方法有:

  • void PreOrderTraversal(BinTree BT); //先序---根、左子树、右子树

  • void InOrderTraversal(BinTree BT); //中序---左子树、根、右子树

  • void PostOrderTraversal(BinTree BT); //后序---左子树、右子树、根

  • void LevelOrderTraversal(BinTree BT); //层次遍历,从上到下、从左到右

2.二叉树的几个重要性质

  • 一个二叉树第i层的最大节点数为 2^i-1^,i≥1。

  • 深度为k的二叉树有最大结点总数为 2^k^-1,k≥1。

  • 对任何非空二叉树T,若n0表示叶结点的个数、n2是度为2的非叶结点个数,那么两者满足关系n0=n2+1。

  • 具有n个结点的完全二叉树的深度k必为log2n+1

3.二叉树的存储结构

1、顺序存储结构

完全二叉树:按从上至下、从左到右顺序存储n个结点的完全二叉树的结点父子关系

  • 非根结点(序号i > 1)的父结点的序号是 [i / 2] ;(向下取整)

  • 结点(序号为i)的左孩子的序号是 2i(2i ≤ n,否则没有左孩子)

  • 结点(序号为i)的右孩子的序号是 2i+1(2i + 1 ≤ n,否则没有右孩子)

一般二叉树也可采用这种顺序存储结构,但是会造成空间浪费

2、链式存储

(1)定义

typedef struct TreeNode *BinTree;
typedef BinTree Position;
struct TreeNode {
		ElementType Data;
		BinTree Left;
		BinTree Right;
}

(2)遍历(递归实现)

先序遍历:

1.先访问根结点; 2.先序遍历其左子树; 3.先序遍历其右子树。

void PreOrderTraversal(BinTree BT) {
	if(BT) {
		printf("%d", BT->Data);
		PreOrderTraversal( BT->Left);
		PreOrderTraversal( BT->Right);
	}
}

中序遍历:

1.中序遍历其左子树 2.访问根结点 3.中序遍历其右子树。

void InOrderTraversal(BinTree BT) {
	if(BT) {
		InOrderTraversal( BT->Left);
		printf("%d", BT->Data);
		InOrderTraversal( BT->Right);
	}
}

后序遍历:

1.后序遍历其左子树 2.后序遍历其右子树。 3.访问根结点

void PostOrderTraversal(BinTree BT) {
	if(BT) {
		PostOrderTraversal( BT->Left);
		PostOrderTraversal( BT->Right);
		printf("%d", BT->Data);
	}
}

(2)遍历(非递归实现)

基本思路:使用堆栈或队列

中序遍历非递归遍历算法

  • 遇到一个结点,就把它压栈,并去遍历它的左子树;

  • 当左子树遍历结束后,从栈顶弹出这个结点并访问它;

  • 然后按其右指针再去中序遍历该结点的右子树。

void InOrderTraversal(BinTree BT) {
	BinTree T = BT;
	Stack S = CreatStack(MaxSize);//创建并初始化堆栈S
	while( T || !IsEmpty(S) ) {
		while(T) {//一直向左并将沿途结点压入堆栈
			Push(S, T);
			T = T->Left;
		}
		if( !IsEmpty(S) ) {
			T = Pop(S);	//结点弹出堆栈
			printf("%5d", T->Data);//访问结点
			T = T->Right;//转向右子树
		}
	}
}

层序遍历

  • 需要一个存储结构保存暂时不访问的结点(堆栈、队列) 队列实现:遍历从根节点开始,首先将根节点入队,然后开始执行循环:结点出队、访问该节点、其左右儿子入队 1.根结点入队; 2.从队列中取出一个元素; 3.访问该元素所指结点; 4.若该元素所指结点的左、右孩子结点非空,将其左、右孩子的指针顺序入队。

void LevelOrderTraversal(BinTree BT) {
	Queue Q;  BinTreee T;
	if ( !BT ) return;	//若是空树直接返回
	Q = CreateQueue(MaxSize);//创建并初始化队列Q
	AddQ(Q, BT);
	while( !IsEmpty(Q) ) {
		T = DeleteQ(Q);
		printf("%d\n", T->Data);//访问结点
		if(T->Left) AddQ(Q, T->Left);//将左孩子放入队列
		if(T->Right) AddQ(Q, T->Right);//将右孩子放入队列
	}
}

补充知识 数据管理的基本操作之查找:根据某个给定关键字K,从集合R中找出关键字与K相同的记录,分为静态查找与动态查找 静态查找:集合中记录是固定的,没有插入和删除操作,只有查找。 法1:顺序查找 (哨兵概念:在数组的边界上设一个值,碰到哨兵循环就可以结束了,可以少一个分支判断)复杂度O(n); 法2:二分查找 (前提:数组连续且有序) 动态查找:集合中记录时动态变化的,除查找外还可能发生插入和删除

二叉树T: 一个有穷的结点集合。 这个结点可以为空 若不为空,则它是由根结点和称为其左子树TL和右子树TR的两个不相交的二叉树组成 二叉树具体五种基本形态 a空树 b只有一个结点 c有一个结点和左子树 d有一个结点和左子树 e有一个结点和左右子树 PS:二叉树的子树有左右顺序之分

几种特殊二叉树 二叉树的抽象数据类型定义 类型名称:二叉树 数据对象集:一个有穷的结点集合。 若不为空,则由根结点和其左、右二叉子树组成。 操作集:BT∈BinTree,Item∈ElementType,重要操作有:

满二叉树:除最后一层无任何子节点外,每一层上的所有结点都有两个子结点的二叉树,区别于完全二叉树

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述