二叉树

这篇博客详细介绍了二叉树的各种遍历方法,包括层次遍历、按之字形顺序打印,以及递归相关的操作如求最大深度、最小深度、判断平衡二叉树。此外,还讲解了二叉树的镜像、重构和查找二叉树的下一个结点的算法和实现思路。
摘要由CSDN通过智能技术生成

一、二叉树层次遍历

从上往下打印二叉树

利用队列从上至下,从左至右,依次存储每一个结点。

# -*- coding:utf-8 -*-
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None
class Solution:
    # 返回从上到下每个节点值列表,例:[1,2,3]
    def PrintFromTopToBottom(self, root):
        # write code here
        res=[]
        q=[]
        if not root:
            return []
        q.append(root)//根节点加入队列中
        while(q):
            res.append(q[0].val)//队头元素的值
            if q[0].left://判读对头节点的左右节点加入队列
                q.append(q[0].left)
            if q[0].right:
                q.append(q[0].right)
            q.pop(0)
        return res
import java.util.ArrayList;
import java.util.Queue;
import java.util.LinkedList;
/**
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) {
        ArrayList<Integer> res=new ArrayList<>();
        Queue<TreeNode> queue=new LinkedList<>();//queue是抽象类,要用LinkedList创建
        if(root==null) return res;
        queue.add(root);
        while(!queue.isEmpty()){
            res.add(queue.peek().val);//peek()取对头元素
            TreeNode node=queue.poll();//将队头元素删除,没有则返回null
            if(node.left!=null) queue.add(node.left);
            if(node.right!=null) queue.add(node.right);
        }
        return res;
    }
}

把二叉树打印成多行

每行记录当前行个数和下一行个数;或者当前行列表,下一行列表。
每行记录成一个列表,然后总的res
python
思路:利用层次遍历,但加入本层levelque和下一层nextlevel,res存放最终值
1.根节点加入levelque中
2.while leveque:针对每层创建一个nextlevel(存入左子树和右子树),curvalue存放当前层的值
3.然后将curvalue加入res中,nextlevel给level

# -*- coding:utf-8 -*-
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None
class Solution:
    # 返回二维列表[[1,2],[4,5]]
    def Print(self, pRoot):
        # write code here
        if not pRoot:
            return []
        levelque=[pRoot]
        res=[]
        while levelque:
            curvalue=[]
            nextlevel=[]
            for i in levelque:
                curvalue.append(i.val)
                if  i.left:
                    nextlevel.append(i.left)
                if  i.right:
                    nextlevel.append(i.right)
            if curvalue:
                res.append(curvalue)
            levelque=nextlevel
        return res

层次遍历,利用current count和nextcount计数。

import java.util.*;


/*
public class TreeNode {
    int val = 0;n
    TreeNode left = null;
    TreeNode right = null;

    public TreeNode(int val) {
        this.val = val;

    }

}
*/
public class Solution {
    ArrayList<ArrayList<Integer> > Print(TreeNode pRoot) {
        ArrayList<ArrayList<Integer>> res=new ArrayList<>();
        ArrayList<Integer> list=new ArrayList<>();
        if(pRoot==null) return res;
        Queue<TreeNode> q=new LinkedList<>();
        int curcount=0;
        int nextcount=1;
        q.add(pRoot);
        while(!q.isEmpty()){
            TreeNode cur=q.poll();
            curcount+=1;
            list.add(cur.val);
            if(cur.left!=null)q.add(cur.left);
            if(cur.right!=null) q.add(cur.right);
            if(curcount==nextcount){
                res.add(list);
                curcount=0;
                nextcount=q.size();
                list=new ArrayList<Integer>();
            }
        }
        return res;
    }
}

按之字形顺序打印二叉树

思路一:按层次遍历,偶数行,逆序加入

# -*- coding:utf-8 -*-
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None
class Solution:
    def Print(self, pRoot):
        # write code here
        if not pRoot:
            return []
        levelque=[pRoot]
        righttoleft=False
        res=[]
        while levelque:
            curvalue=[]
            nextlevel=[]
            for i in levelque:
                curvalue.append(i.val)
                if  i.left:
                    nextlevel.append(i.left)
                if  i.right:
                    nextlevel.append(i.right)
            if righttoleft:
                curvalue.reverse()
            if curvalue:
                res.append(curvalue)
            levelque=nextlevel
            righttoleft= not righttoleft
        return res
public class Solution {
    ArrayList<ArrayList<Integer> > Print(TreeNode pRoot) {
        ArrayList<ArrayList<Integer>> res=new ArrayList<>();
        ArrayList<Integer> list=new ArrayList<>();
        if(pRoot==null) return res;
        Queue<TreeNode> q=new LinkedList<>();
        int curcount=0;
        int nextcount=1;
        boolean righttoleft=false;
        q.add(pRoot);
        while(!q.isEmpty()){
            TreeNode cur=q.poll();
            curcount+=1;
            list.add(cur.val);
            if(cur.left!=null)q.add(cur.left);
            if(cur.right!=null) q.add(cur.right);
            if(curcount==nextcount){
                if(!righttoleft) res.add(list);
                else{
                    Collections.reverse(list);
                    res.add(list);
                }
                curcount=0;
                nextcount=q.size();
                list=new ArrayList<Integer>();
                righttoleft=!righttoleft;
            }
        }
        return res;
    }
}

思路二:利用两个stack,后进先出特性

import java.util.ArrayList;
import java.util.Stack;
/*
public class TreeNode {
    int val = 0;
    TreeNode left = null;
    TreeNode right = null;

    public TreeNode(int val) {
        this.val = val;

    }

}
*/
public class Solution {
    public ArrayList<ArrayList<Integer> > Print(TreeNode pRoot) {
        ArrayList<ArrayList<Integer>> res=new ArrayList<>();
        if(pRoot==null) return res;
        Stack<TreeNode> s1=new Stack<>();
        Stack<TreeNode> s2=new Stack<>();
        s1.push(pRoot);
        int level=1;
        while(!s1.isEmpty()||!s2.isEmpty()){
            ArrayList<Integer> list=new ArrayList<>();
            if(level++%2!=0){//层级,奇数,偶数
                while(!s1.isEmpty()){
                    TreeNode cur=s1.pop();
                    list.add(cur.val);
                    if(cur.left!=null) s2.push(cur.left);//s2逆序,先进后厨
                    if(cur.right!=null) s2.push(cur.right);
                }
            }
            else{//逆序
                while(!s2.isEmpty()){
                    TreeNode cur=s2.pop();
                    list.add(cur.val);
                    if(cur.right!=null) s1.push(cur.right);
                    if(cur.left!=null) s1.push(cur.left);
                }
            }
            res.add(list);
        }
        return res;
    }
}

二、递归相关

二叉树的最大深度

思路:
递归:左树右树的深度最大值+1

# -*- coding:utf-8 -*-
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None
class Solution:
    def TreeDepth(self, pRoot):
        # write code here
        if not pRoot:
            return 0
        lefttree=self.TreeDepth(pRoot.left)
        righttree=self.TreeDepth(pRoot.right)
        return max(lefttree,righttree)+1
public class TreeNode {
    int val = 0;
    TreeNode left = null;
    TreeNode right = null;
 
    public TreeNode(int val) {
        this.val = val;
    }
}
public class Solution {
    public int TreeDepth(TreeNode root) {
        if(root==null) return 0;
        return Math.max(TreeDepth(root.left),TreeDepth(root.right))+1;
    }
}

非递归:
层次遍历
利用currentcount和nextcount来记录当前层的应遍历的节点个数,满足遍历完后,depth+=1

public class Solution {
    public int TreeDepth(TreeNode root) {
        if(root==null) return 0;
        Queue<TreeNode> queue=new LinkedList<>();
        queue.add(root);
        int depth=0;
        int currentcount=0;//记录当前层的节点个数
        int nextcount=1;//当前层应有的节点个数
        while(!queue.isEmpty()){
            TreeNode currentnode=queue.poll();
            currentcount+=1;
            if(currentnode.left!=null) queue.add(currentnode.left);
            if(currentnode.right!=null) queue.add(currentnode.right);
            if(currentcount==nextcount){//满足时,表示当前层遍历完,深度可以加1
                currentcount=0;
                nextcount=queue.size();
                depth+=1;
            }
        }
        return depth;
    }
}

最小深度

import java.util.*;
public class Solution {
    public int run(TreeNode root) {
        if(root==null)
            return 0;
        else if(root.left==null && root.right==null)
            return 1;
        else if(root.left==null)
            return run(root.right)+1;
        else if(root.right==null)
            return run(root.left)+1;
        return Math.min(run(root.left),run(root.right))+1;
    }
}

思路二:广度遍历(BFS),用linkedlist创建queue,注意利用queue.size()判断每层节点数queue.poll()利用level记录,遇到子节点(无左右子树的节点)则返回深度level

/**
 * Definition for binary tree
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
import java.util.*;
public class Solution {
    public int run(TreeNode root) {
        if(root==null)
            return 0;
        if(root.left==null && root.right==null)
            return 1;
        Queue<TreeNode> queue=new LinkedList<TreeNode>();
        queue.add(root);
        int level=1;
        while(!queue.isEmpty()){
            int size=queue.size();//每层看有几个节点
            for(int i=0;i<size;i++){//对于每层的每个节点判断
                TreeNode node=queue.poll();
                if(node.left!=null)
                    queue.add(node.left);
                if(node.right!=null)
                    queue.add(node.right);
                if(node.left==null && node.right==null)//如果左右子树都为空则表示该节点为叶子节点,当前既是最小深度
                    return level;
            }
            level++;
        }
        return level;
    }
}

平衡二叉树

二叉树的左右子树高度差不超过1
先计算二叉树的最大高度
遍历每一个节点,根据该结点的左右子树高度差判断是否平衡,然后递归地对左右子树进行判断。
超过1,False;不超过1,左右子树都判断

# -*- coding:utf-8 -*-
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None
class Solution:
    def IsBalanced_Solution(self, pRoot):
        # write code here
        if pRoot is None:#递归退出条件
            return True
        if abs(self.TreeDepth(pRoot.left)-self.TreeDepth(pRoot.right))>1:#根节点的左子树右子树判断
            return False
        return self.IsBalanced_Solution(pRoot.left) and self.IsBalanced_Solution(pRoot.right)#左子树右子树分别递归
    def TreeDepth(self,Root):#判断树的深度
        if Root is None:
            return 0
        left=self.TreeDepth(Root.left)
        right=self.TreeDepth(Root.right)
        return max(left,right)+1

三、二叉树的镜像和对称

1.对称的二叉树

判断比较
思路:
定义一个比较函数比较左右子树
1.左子树为空,返回右子树是否为空
2.右子树为空,返回false
3.左右节点的值不同,返回false
4.递归比较 左子树的右子树和右子树的左子树 and 右子树的左子树和左子树的右子树

# -*- coding:utf-8 -*-
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None
class Solution:
    def isSymmetrical(self, pRoot):
        # write code here
        if not pRoot:
            return True
        return self.compare(pRoot.left,pRoot.right)
    def compare(self,leftroot,rightroot):
        if leftroot==None:
            return rightroot==None
        if rightroot==None:
            return False
        if leftroot.val!=rightroot.val:
            return False
        return self.compare(leftroot.right,rightroot.left) and self.compare(leftroot.left,rightroot.right)

2.二叉树的镜像

将二叉树转成镜像,交换节点和递归
思路一:递归:若root为空,若root.left and root.right都为空,则返回;
其次进行左右节点交换;
然后左节点不空,则左节点Mirror;右节点不空,则右节点Mirror

# -*- coding:utf-8 -*-
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None
class Solution:
    # 返回镜像树的根节点
    def Mirror(self, root):
        # write code here
        if root is  None:
            return
        if (root.left is None and root.right is None):
            return
        tmp=root.left
        root.left=root.right
        root.right=tmp
        if root.left is not None:
            self.Mirror(root.left)
        if root.right is not None:
            self.Mirror(root.right)
        return root

四、重构二叉树

根据前序遍历和中序遍历,重建二叉树
思路一:找到中序中根节点所在位置,分为左子树,右子树递归调用重建

# -*- coding:utf-8 -*-
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None
class Solution:
    # 返回构造的TreeNode根节点
    def reConstructBinaryTree(self, pre, tin):
        # write code here
        if len(pre)==0 or len(tin)==0:
            return None
        root=TreeNode(pre[0])//创建根节点
        pos=tin.index(pre[0])
        root.left=self.reConstructBinaryTree(pre[1:pos+1],tin[:pos])//左子树
        root.right=self.reConstructBinaryTree(pre[pos+1:],tin[pos+1:])//右子树
        return root

五、二叉树的下一个结点

思路:
1.空,返回空
2.该节点存在右子节点,则指针指向该节点的右子节点,循环判断右子节点的左节点,直到左子节点为空
3.该节点不存在右子节点,循环条件(该节点的下一个节点不为空)创建一个根节点(指向该节点的下一个节点),若该节点为根节点的左子节点,返回该节点;否则继续.next

# -*- coding:utf-8 -*-
# class TreeLinkNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None
#         self.next = None
class Solution:
    def GetNext(self, pNode):
        # write code here
        if pNode==None:
            return None
        if pNode.right!=None:
            pNode=pNode.right
            while(pNode.left!=None):
                pNode=pNode.left
            return pNode
        while pNode.next!=None:
            root=pNode.next
            if root.left==pNode:
                return root
            pNode=pNode.next
        return None
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值