一周刷爆LeetCode,左程云老师-二叉树

二叉树

递归和非递归三种方式(PreOrder, InOrder, PostOrder)

递归
public static void f(Node head)
{
	if (head == null)
	{
		return;
	}
	//先序遍历
    System.out.print(head.value + " ");
	f(head.left);
	//中序遍历
    System.out.print(head.value + " ");
	f(head.right);
	//后序遍历
    System.out.print(head.value + " ");
}
非递归
先序遍历

1、从栈中弹出curr, 打印cur

2、先右孩子,再左孩子入栈,如果有的话

3、栈为空或者栈没有东西弹了,停止

public static void preOrderUnRecur(Node head)
    {
        System.out.println("preOrder:");
        if (head != null)
            //入栈条件是节点非空
        {
            Stack<Node> stack = new Stack<Node>();

            stack.add(head);

            while (!stack.empty())
            {
                head = stack.pop();
                System.out.println(head.val + " ");

                if (head.left != null)
                {
                    stack.push(head.left);
                }
                if(head.right != null)
                {
                    stack.push(head.right);
                }
            }
        }
        System.out.println();

    }
后序遍历

先序遍历入栈顺序是中左右,中放到收集栈,左右入栈然后再出栈到收集栈

收集栈变成中右左再出栈就变成了左右中

public static void posOrderUnRecur(Node head)
    {
        System.out.println("PosOrder:");

        if (head != null)
        {
            Stack<Node> stack1 = new Stack<Node>();
            Stack<Node> stack2 = new Stack<Node>();
            stack1.push(head);
            while (!stack1.isEmpty())
            {
                head = stack1.pop();
                stack2.push(head); //先序的打印变成压栈到s2

                if (head.left != null)
                {
                    stack1.push(head.left);
                }
                if (head.right != null)
                {
                    stack1.push(head.right);
                }

                while(!stack2.isEmpty())
                {
                    System.out.println(stack2.pop().value + " ");
                }
            }
        }
        System.out.println();
    }
中序遍历

1、子树整条左边界依次进栈,如果没有进入阶段二

2、栈中弹出cur并打印,cur的右子树重复阶段一

public static void InOrderUnRecur(Node head)
    {
        System.out.println("InOrder:");
        if (head != null)
        {
            Stack<Node> stack = new Stack<Node>();
            Node cur = head;
            while (!stack.isEmpty() || cur != null)
            {
                //当栈为空或者节点为空,跳出循环
                if (cur != null)
                {
                    stack.push(cur);
                    cur = cur.left;
                }
                else
                {
                    cur = stack.pop();
                    System.out.println(cur.value + " ");
                    cur = cur.right;
                }
            }
        }
        System.out.println();
    }

宽度遍历

队列顺序遍历

public static void process(Node head)
    {
        while (head != null)
        {
            Queue<Node> queue = new LinkedList<>();
            queue.add(head);
            while(!queue.isEmpty())
            {
                Node cur = queue.poll();
                System.out.println(cur.value + " ");
                if (cur.left != null)
                {
                    queue.add(cur.left);
                }

                if (cur.right != null)
                {
                    queue.add(cur.right);
                }
            }
        }
        System.out.println();
    }

二叉树最大层数

在宽度遍历的基础上,用Map来存储对应节点的层数

用cLevel, cNodes, max – 当前层数,当前层节点数,最大节点数

public static void process1(Node head)
    {
        while (head != null)
        {
            HashMap<Node, Integer> levelMap = new HashMap<>();
            Queue<Node> queue = new LinkedList<>();
            queue.add(head);
            levelMap.put(head, 1);

            int cLevel = 1; // 当前层数
            int cNodes = 0; // 当前层数节点数
            int max = 0; //一层最大节点数
            while(!queue.isEmpty() || head != null)
            {
                Node cur = queue.poll();
                int level = levelMap.get(cur);
                System.out.println("Node:" +cur.value + " Level: " + level);
                if (level == cLevel)
                {
                    cNodes ++;
                }
                else
                {
                    //level != cLevel
                    max = Math.max(max, cNodes);
                    cLevel ++;
                    cNodes = 1;
                }
                if (cur.left != null)
                {
                    queue.add(head.left);
                    levelMap.put(head.left, level + 1);
                }
                if (cur.right != null)
                {
                    queue.add(head.right);
                    levelMap.put(head.left, level + 1);
                }
                
            }
            // 最后一层
            System.out.println("Node:" +cur.value + " Level: " + level);
            max = Math.max(max, cNodes);
            System.out.println(max);
        }
        
    }

二叉树的递归套路

搜索二叉树

搜索二叉树定义:左子树的值均小于右子树的值

中序遍历二叉树

在打印的时刻变成比较

public static int preValue = Integer.
完全二叉树

宽度遍历

①有右孩子没有左孩子返回false

②在满足一的条件下,遇到第一个左右孩子不双全的节点,后续都要是叶子节点才符合

满二叉树

节点数 N 最大深度为l

N = 2^l - 1

平衡二叉树

左树的高度和右树的高度差不超过1

一、左树平衡

二、右树平衡

三、|左树和右树的高度差|<=1

二叉树的前驱和后继节点

在二叉树中找到一个节点的后继节点
【题目】现在有一种新的二叉树节点类型如下:
public class Node {
public int value ;
public Node left;
public Node right;

public Node parent;

public Node(int val)

{
value = val ;

}

该结构比普通二叉树节点结构多了一个指向父节点的parent指针。
假设有一棵Node类型的节点组成的二叉树,树中每个节点的parent指针都正确地指向自己的父节点,头节点的parent指向null。
只给一个在二叉树中的某个节点node,请实现返回node的后继节点的函数。在二叉树的中序遍历的序列中, node的下一个节点叫作node的后继节点。

在这里插入图片描述

public static Node getSuccessorNode(Node node)
    {
        //返回后继节点
        if (node == null)
        {
            return null;
        }
        if (node.right != null)
        {
            // 有右孩子情况
            return getLeftMost(node.right);
        }
        else
        {
            // 没有右子树情况
            Node parent = node.parent;
            while (parent != null && parent.left != node) {
                // 当前节点是父母节点的右孩子
                node = parent;
                parent = node.parent;
            }
            return parent;
        }
    }

二叉树的序列化和反序列化

就是内存里的一棵树如何变成字符串形式,又如何从字符串形式变成内存里的树

作用:判断一颗二叉树是不是另一棵二叉树的子树?

在这里插入图片描述

public static String serialByPre(Node head)
    {
        //序列化
        if (head == null)
        {
            return "#-";
        }
        String res = head.getValue() + "-";
        res += serialByPre(head.left);
        res += serialByPre(head.right);
        return res;
    }
    public static Node reconByPreString(String preStr)
    {
        // 反序列化
        String[] values = preStr.split("-");
        Queue<String> queue = new LinkedList<String>();
        for (int i = 0; i < values.length; i++)
        {
            queue.add(values[i]);
        }
        return reconByPreOrder(queue);
    }

    public static Node reconPreOrder(Queue<String> queue)
    {
        // 根据队列建出一棵树
        String value = queue.poll();
        if (value == "#")
        {
            return null;
        }
        Node node = new Node(Integer.valueOf(value));
        head.left =  reconPreOrder(queue);
        head.right = reconPreOrder(queue);
        return head;
    }

折纸问题

例子

分析我们可以得知

①第一个折痕是凹的

②一个折痕再对折一次上面的折痕是凹的,下面的折痕是凸的(节点的左孩子是凹的,右孩子是凸的)

在这里插入图片描述

public class 二叉树PaperFolding
{
    public static void printAllFolds(int N)
    {
        printProcess(1, N, true);
    }

    private static void printProcess(int i, int N, boolean down)
    {
        // i层开始, N层结束, down为True表示凹
        if (i > N)
        {
            return ;
        }
        printProcess(i + 1, N, true);
        System.out.println(down ? "凹" : "凸");
        printProcess(i + 1, N, false);
    }


    public static void main(String[] args)
    {
        int N = 3;
        printAllFolds(N);

;    }
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值