数据结构-二叉树(Binary Tree)
1、二叉树(Binary Tree)
是n(n>=0)个结点的有限集合,该集合或者为空集(空二叉树),或者由一个根节点和两棵互不相交的,分别称为根节点的左子树和右子树的二叉树组成。

2、特数二叉树
1)斜二叉树

所有的结点都只有左子树的二叉树叫做左斜树
所有的结点都只有右子树的二叉树叫做右斜树
相当于链表,所以线性结构可以理解为是树的一种极其特殊的表现形式
2)满二叉树(完美二叉树)

所有分支结点都存在左子树和右子树。
所有叶子结点都在同一层
3)完全二叉树

对树按照上->下,左->右,编号为i的与满二叉树中为i的位置相同。
3、二叉树的重要性质
性质一:第i层最大结点数位2^(i-1)个,(i>=1)
性质二:深度为k的二叉树至多有2^k-1个结点
性质三:叶结点n0与度为2的结点n2的个数关系n0=n2+1
性质四:具有n个结点的完全二叉树的深度为[log2n]+1
性质五:对一棵有n个结点的完全二叉树,从第一层到最大层,对任一结点i(1=<i<=n)有:
注意:下标是从1开始的。
1.非根节点的父节点序号是[i/2]
2.结点(序号i)的左孩子为2i,若2i>n没有左孩子
3.结点(序号i)的右孩子为2i+1,若2i+1>n没有右孩子

但一般数组下标是从0开始的:

树中的每个位置,无论是否存在节点,都对应于数组中的一个位置,树中没有节点的在数组中用0或者null表示。
假设节点的索引值为index,那么节点的左子节点是 2*index+1,节点的右子节点是 2*index+2,它的父节点是 (index-1)/2。
4、二叉树的顺序存储结构
一般树很难用数组存储,但完全二叉树可以,(从上->下,从左->右,层序遍历)。同时可以利用完全二叉树的性质5,快速获得结点的双亲与孩子位置。


二叉树的顺序存储结构就是用一维数组存储二叉树中的结点,并且结点的存储位置,可以使用性质五来提现结点之间关系。这就是完全二叉树的优越性。
补充:对于一般二叉树也可以使用顺序存储(不过需要对空结点进行补全为^,变为一棵完全二叉树先)
我们需要结合数的结构来考虑,一棵普通的二叉树能否使用该方法。
如果是接近完全二叉树的二叉树,我们可以补全,
但是对于一棵类似于右斜二叉树,则完全没有必要,会大量浪费空间

5、二叉链表

//二叉树的二叉链表结点结构定义
typedef struct BiTNode //结点结构
{
TElemType data; //结点数据
struct BiTNode *lchild, *rchild; //左右孩子指针
}BiTNode,*BiTree;

6、二叉树的遍历(递归方式)
1)前序遍历(根左右,从根节点开始遍历)

void PreOrderTraversal(BinTree BT)
{
if (BT)
{
printf("%d", BT->data);
PreOrderTraversal(BT->lchild);
PreOrderTraversal(BT->rchild);
} }
2)中序遍历(左根右,注意从最左侧叶子节点开始遍历)

void InOrderTraversal(BinTree BT)
{
if (BT)
{
InOrderTraversal(BT->lchild);
printf("%d", BT->data);
InOrderTraversal(BT->rchild);
}
}
3)后序遍历(左右根,依然从最左侧叶子节点开始)

void PostOrderTraversal(BinTree BT)
{
if (BT)
{
PostOrderTraversal(BT->lchild);
PostOrderTraversal(BT->rchild);
printf("%d", BT->data);
}
}
4)层序遍历(顺序存储)利用队列。

import java.util.*;
/**
public class TreeNode {
int val = 0;
TreeNode left = null;
TreeNode right = null;
public TreeNode(int val) {
this.val = val;
}
}
*/
public class Solution {
public ArrayList<Integer> PrintFromTopToBottom(TreeNode root) {
Queue<TreeNode> queue=new LinkedList<>();
ArrayList<Integer> list=new ArrayList<Integer>();
if(root==null)
return list;
queue.offer(root);
while(!queue.isEmpty())
{
int size=queue.size();
for(int i=0;i<size;i++)
{
TreeNode node=queue.poll();
list.add(node.val);
if(node.left!=null) queue.offer(node.left);
if(node.right!=null) queue.offer(node.right);
}
}
return list;
}
}
二叉树前、中、后三种遍历的非递归实现方式:

前序和后序遍历:前序遍历和后序遍历归为一类,所用思想基本一模一样:
前序遍历的步骤为 :
①对root进行异常处理
②将root压入栈
③while循环遍历,终止条件为栈为空,所有元素均已处理完
④从栈顶取元素读,取并存入结果
⑤将取出元素的右、左节点分别压入栈内,以便下次循环取元素时为本次节点的左,右子节点.
运用辅助栈,保存遍历到的节点(用栈后入先出的特性,控制已经遍历到的节点的访问顺序). 以前序深度优先遍历为例,先访问根节点,然后访问左树,左树全部访问完了,再访问右树
后续遍历思想: 左-右-根;可以视为, 根-右-左,然后结果转置即可. 如前面示意图,根右左,访问顺序则为:ACFBED;可以看出,这样访问刚好为后续遍历的转置. 根右左访问与前序(根左右)遍历操作思想一模一样
①前序遍历
/**
* 前序遍历,迭代法
*/
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> result = new ArrayList<>();
if (root == null) return result;
Stack<TreeNode> stack = new Stack<>();
stack.push(root);
while (!stack.isEmpty()) {
TreeNode node = stack.pop();
result.add(node.val);
if (node.right != null) stack.push(node.right); //先压入右节点,后出栈
if (node.left != null) stack.push(node.left); //后压入左节点,先出栈
}
return result;
}
②后序遍历
public List<Integer> postorderTraversal(TreeNode root) {
List<Integer> result = new ArrayList<>();
if(root == null) return result;
Deque<TreeNode> stack=new ArrayDeque<>();
stack.push(root);
while(!stack.isEmpty()){
TreeNode node=stack.pop();
result.add(node.val); //结点添加顺序为 根右左
if(node.left!=null) stack.push(node.left);
if(node.right!=null) stack.push(node.right);
}
Collections.reverse(result); //反转为:左右根
return result;
}
③中序遍历
中序遍历思路: 中序遍历迭代法思路不同于前序和后序.
①首先针对对当前节点,一直对其左子树迭代并将非空节点入栈
②节点指针迭代为空(到树底了)后不再入栈,然后取栈顶元素,存结果;
③将当前指针用出栈的节点的右子节点替代,然后回到第一步继续迭代,直到当前节点为空且栈为空.
public List<Integer> inorderTraversal(TreeNode root){
List<Integer> result = new ArrayList<>();
if(root==null) return result;
Deque<TreeNode> stack = new ArrayDeque<>();
while (root!=null||!stack.isEmpty()){
while(root!=null){
stack.push(root);
root=root.left;
}
TreeNode node=stack.pop();
result.add(node.val);
root=node.right;
}
return result;
}
数据结构-二叉树(Binary Tree)的更多相关文章
- 数据结构-二叉树(Binary Tree)
#include <stdio.h> #include <string.h> #include <stdlib.h> #define LIST_INIT_SIZE ...
- 算法与数据结构基础 - 二叉树(Binary Tree)
二叉树基础 满足这样性质的树称为二叉树:空树或节点最多有两个子树,称为左子树.右子树, 左右子树节点同样最多有两个子树. 二叉树是递归定义的,因而常用递归/DFS的思想处理二叉树相关问题,例如Leet ...
- [Swift]LeetCode968.监控二叉树 | Binary Tree Cameras
Given a binary tree, we install cameras on the nodes of the tree. Each camera at a node can monitor ...
- 二叉树(Binary Tree)相关算法的实现
写在前面: 二叉树是比较简单的一种数据结构,理解并熟练掌握其相关算法对于复杂数据结构的学习大有裨益 一.二叉树的创建 [不喜欢理论的点我跳过>>] 所谓的创建二叉树,其实就是让计算机去存储 ...
- Python与数据结构[3] -> 树/Tree[0] -> 二叉树及遍历二叉树的 Python 实现
二叉树 / Binary Tree 二叉树是树结构的一种,但二叉树的每一个节点都最多只能有两个子节点. Binary Tree: 00 |_____ | | 00 00 |__ |__ | | | | ...
- Python数据结构——二叉树的实现
1. 二叉树 二叉树(binary tree)中的每个节点都不能有多于两个的儿子. 1.1 二叉树列表实现 如上图的二叉树可用列表表示: tree=['A', #root ['B', #左子树 ['D ...
- [数据结构]——二叉树(Binary Tree)、二叉搜索树(Binary Search Tree)及其衍生算法
二叉树(Binary Tree)是最简单的树形数据结构,然而却十分精妙.其衍生出各种算法,以致于占据了数据结构的半壁江山.STL中大名顶顶的关联容器--集合(set).映射(map)便是使用二叉树实现 ...
- 数据结构《9》----Threaded Binary Tree 线索二叉树
对于任意一棵节点数为 n 的二叉树,NULL 指针的数目为 n+1 , 线索树就是利用这些 "浪费" 了的指针的数据结构. Definition: "A binary ...
- [LeetCode] Serialize and Deserialize Binary Tree 二叉树的序列化和去序列化
Serialization is the process of converting a data structure or object into a sequence of bits so tha ...
随机推荐
- Apache Flink系列-④有状态函数
有状态函数:独立于平台的有状态无服务器堆栈 这是一种在现代基础设施上创建高效.可扩展且一致的应用程序的简单方法,无论规模大小. 有状态函数是一种API,它通过为无服务器架构构建的运行时简化了分 ...
- PAT练习--1050 String Subtraction (20 分)
题⽬⼤意:给出两个字符串,在第⼀个字符串中删除第⼆个字符串中出现过的所有字符并输出. 这道题的思路:将哈希表里关于字符串s2的所有字符都置为true,再对s1的每个字符进行判断,若Hash[s1[i] ...
- SpringMVC 配置 & 初识 & 注解 &重定向与转发
初识 在web.xml 中注册DispatcherServlet <servlet> <servlet-name>springmvc</servlet-name> ...
- [cf]Codeforces Round #784(Div 4)
由于一次比赛被虐得太惨,,生发开始写blog的想法,于是便有了这篇随笔(找了个近期的cf比赛练练手(bushi))第一次写blog,多多包涵. 第二场cf比赛,第一场打的Div2,被虐太惨,所以第二场 ...
- 干货|给小白的 Nginx 10分钟入门指南
一个执着于技术的公众号 前言 今天主要对Nginx Web服务软件进行介绍,作为HTTP服务软件的后起之秀,Nginx与它的老大哥Apache相比有很多改进之处,比如,在性能上,Nginx占用的系统资 ...
- 动手实操丨RC522射频卡模块与IC卡完成充值消费查询的技术实现思路
摘要:一文手把手教你利用RC522射频卡模块与IC卡完成充值消费查询的技术实现思路. 本文分享自华为云社区<RC522射频卡模块与IC卡完成充值消费查询的技术实现思路 ...
- clientWidth、offsetWidth、scrollWidth……
1.元素视图属性 clientWidth:元素内容可视区宽度(水平方向 width + 左右 padding). clientHeight:元素内容可视高度(垂直方向 height + 上下paddi ...
- 如何彻底禁止 macOS Monterey 自动更新,去除更新标记和通知
请访问原文链接:如何彻底禁止 macOS Monterey 自动更新,去除更新标记和通知,查看最新版.原创作品,转载请保留出处. 作者主页:www.sysin.org 随着 macOS Montere ...
- 云厂商 RDS MySQL 怎么选
1. 摘要 为了让大家更好的了解各云厂商在RDS MySQL数据库功能上的差异,也为给准备上云的同学做个参考,本文将对阿里云.腾讯云.华为云和AWS 的 RDS MySQL数据库进行对比说明. 从一个 ...
- JS运算符,流程控制,函数,内置对象,BOM与DOM
运算符 1.算数运算符 运算符 描述 + 加 - 减 * 乘 / 除 % 取余(保留整数) ++ 递加 - - 递减 ** 幂 var x=10; var res1=x++; '先赋值后自增1' 10 ...