树型结构(非线性),递归定义,子树之间不能有交集
结点的度:一个结点含有子树的个数称为该结点的度
树的度:一棵树中,所有结点度的最大值称为树的度
叶子结点:度为0的结点
一、概念
要么为空,要么一个根节点加两棵树(左子树和右子树),每个节点的度不能超过2
二、特殊二叉树
1.满二叉树
每层的结点数都达到最大值
总共的结点个数(k层):2ᴷ-1
2.完全二叉树
(深度为k,n个结点)
从0到n-1结点一 一对应,满二叉树是特殊的完全二叉树
三、二叉树的性质
- 第i层最多有2的(i-1)次方个结点(i>0)
- 深度为k的最大结点数是2ᴷ-1(k≥0)
- 叶结点个数为n0,度为2的非叶结点个数为n2,则有n0=n2+1(每生两个孩子就多一个叶子)
- n个节点的完全二叉数深度k为㏒(n+1)(以2为底)取整
- n个结点的完全二叉树,从上至下从左至右编号,已知父亲节点下标是i,则左孩子节点的下表是2i+1,右孩子节点的下表是2i+2(就是根节点编号从0开始)
- 总边数=总结点数-1(除了根,每个节点都有一条边,总边数等于度数之和,你把节点的度想象成向下的手)
例题:在具有2n个结点的完全二叉数中,叶子结点个数为_。
答案:n(提示:要考虑到结点数的奇偶,偶数结点就多一个,所以n=n0+1+n2,奇数结点就是n=n0+0+n2)
四、二叉树的存储与遍历
1.存储结构
- 顺序存储
- 链式存储
2.遍历方式
- 前序遍历(根左右)
- 顺序遍历(左根右)
- 后序遍历(左右根)
- 层序遍历
例题:

- 前序:ABDEHCFG
- 中序:DBEHAFCG
- 后序:DHEBFGCA
五、代码实现
1.构建二叉树
重点是那种思想,其他方法差不多可以类比
获取节点个数:
思路一:遍历思路,不为空,计数加一
思路二:子问题思路,整棵树的结点个数=左子树的结点个数+右子树的结点个数
获取叶子节点的个数:
遍历思路:root.left == null && root.right == null count++
子问题思路:整棵树的叶子节点个数等于左子树叶子节点的个数加右子树叶子节点的个数
java
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Queue;
public class BinaryTree {
static class TreeNode {
public char val;
public TreeNode left;//左孩子的引用
public TreeNode right;//右孩子的引用
public TreeNode(char val) {
this.val = val;
}
}
/**
* 创建一棵二叉树 返回这棵树的根节点
*
* @return
*/
public TreeNode createTree() {
TreeNode A = new TreeNode('A');
TreeNode B = new TreeNode('B');
TreeNode C = new TreeNode('C');
TreeNode D = new TreeNode('D');
TreeNode E = new TreeNode('E');
TreeNode F = new TreeNode('F');
A.left = B;
A.right = C;
B.left = D;
B.right = E;
C.right = F;
return A;
}
// 前序遍历
public void preOrder(TreeNode root) {
if (root == null){
return;
}
System.out.print(root.val + " ");
postOrder(root.left);
postOrder(root.right);
}
// 中序遍历
void inOrder(TreeNode root) {
if (root == null){
return;
}
postOrder(root.left);
System.out.print(root.val + " ");
postOrder(root.right);
}
// 后序遍历
void postOrder(TreeNode root) {
if (root == null){
return;
}
postOrder(root.left);
postOrder(root.right);
System.out.print(root.val + " ");
}
public static int nodeSize;
/**
* 获取树中节点的个数:遍历思路
*/
void size(TreeNode root) {
if (root == null){
return;
}
nodeSize++;
size(root.left);
size(root.right);
}
/**
* 获取节点的个数:子问题的思路
*
* @param root
* @return
*/
int size2(TreeNode root) {
if (root == null){
return 0;
}
return size2(root.left) + size2(root.right) + 1;
}
/*
获取叶子节点的个数:遍历思路
*/
public static int leafSize = 0;
void getLeafNodeCount1(TreeNode root) {
if (root == null){
return;
}
if (root.left == null && root.right == null){
leafSize++;
}
getLeafNodeCount1(root.left);
getLeafNodeCount1(root.right);
}
/*
获取叶子节点的个数:子问题
*/
int getLeafNodeCount2(TreeNode root) {
if (root == null){
return 0;
}
if (root.left == null && root.right == null){
return 1;
}
return getLeafNodeCount2(root.left)+getLeafNodeCount2(root.right);
}
/*
获取第K层节点的个数
*/
int getKLevelNodeCount(TreeNode root, int k) {
if(root == null){
return 0;
}
if (k == 1){
return 1;
}
return getKLevelNodeCount(root.left,k-1)+getKLevelNodeCount(root.right,k-1);
}
/*
获取二叉树的高度
时间复杂度:O(N)
*/
int getHeight(TreeNode root) {
if (root == null){
return 0;
}
int leftroot = getHeight(root.left);
int rightroot = getHeight(root.right);
return Math.max(leftroot,rightroot)+1;
}
// 检测值为value的元素是否存在
TreeNode find(TreeNode root, char val) {
if (root == null){
return null;
}
if (root.val == val){
return root;
}
TreeNode ret = find(root.left,val);
if (ret != null){
return ret;
}
TreeNode ret2 = find(root.right,val);
if (ret2 != null){
return ret2;
}
return null;
}
//层序遍历
void levelOrder(TreeNode root) {
if (root == null){
return;
}
Queue<TreeNode> queue = new LinkedList<>();
while (!queue.isEmpty()){
TreeNode qul = queue.poll();
System.out.println(qul.val);
if (qul.left != null){
queue.offer(qul.left);
}
if (qul.right != null){
queue.offer(qul.right);
}
}
}
// 判断一棵树是不是完全二叉树
boolean isCompleteTree(TreeNode root) {
if (root == null){
return false;
}
Queue<TreeNode> queue = new LinkedList<>();
while (!queue.isEmpty()){
TreeNode qul = queue.poll();
if (qul != null){
queue.offer(qul.left);
queue.offer(qul.right);
}
else {
break;
}
}
while (!queue.isEmpty()){
TreeNode qul1 = queue.poll();
if (qul1 != null){
return false;
}
}
return true;
}
}
2.判断平衡二叉树
平衡二叉树是指该树所有节点的左右子树的高度相差不超过 1
java
class Solution {
public boolean isBalanced(TreeNode root) {
if(root == null){
return true;
}
return getHeight(root) >= 0;
}
public int getHeight(TreeNode root){
if(root == null){
return 0;
}
int leftH = getHeight(root.left);
if(leftH < 0){
return -1;
}
int rightH = getHeight(root.right);
if(leftH >= 0 && rightH >= 0 && Math.abs(leftH-rightH)<=1){
return leftH > rightH ? leftH + 1 : rightH + 1;
}
else{
return -1;
}
}
}
3.层序遍历
这是一个力扣题,我觉得值得反复看
题目:给你二叉树的根节点 root ,返回其节点值 自底向上的层序遍历 。 (即按从叶子节点所在层到根节点所在的层,逐层从左向右遍历)
java
class Solution {
public List<List<Integer>> levelOrderBottom(TreeNode root) {
List<List<Integer>> ret = new ArrayList<>();
Queue<TreeNode> queue = new LinkedList<>();
if(root == null){
return ret;
}
queue.offer(root);
while(!queue.isEmpty()){
int size = queue.size();
List<Integer> crow = new ArrayList<>();
while(size != 0){
TreeNode cur = queue.poll();
crow.add(cur.val);
if(cur.left != null){
queue.offer(cur.left);
}
if(cur.right != null){
queue.offer(cur.right);
}
size--;
}
ret.add(crow);
}
Collections.reverse(ret);
return ret;
}
}
最后祝大家每天都能坚持学代码,我也会坚持学习,尽量持续更新学习进度,加油