关于二叉树的各种遍历,高度,叶子节点个数,节点个数,是否为完全二叉树,第k层节点个数

目录

二叉树的遍历

 前序遍历

中序遍历

后序遍历

层序遍历

二叉树高度

二叉树叶子节点个数

二叉树节点数量

判断二叉树是否为完全二叉树

第K层节点个数


二叉树的遍历

要了解二叉树遍历的各种方法,首先要明白二叉树前序,中序,后序的遍历方法都是一致的.现在有一棵树,我们对这棵树的遍历都是优先遍历其左数,然后再遍历右树,其顺序的不同只是打印时间的不同,或者入数组,链表的时间不同所以出现了前序,中序,后序遍历.而层序遍历的方法与他们都不同.

 前序遍历

public void preOrder(TreeNode root) {
        if (root == null) {
            return;
        }
        System.out.print(root.val + " ");
        preOrder(root.left);
        preOrder(root.right);
    }

先判断root是否为空,如果不为空,先序遍历root一定是第一个元素,而后对左树进行先序遍历,打印左边的元素,在左树遍历完成之后,最后一个节点为空,返回null,此时自下而上的遍历每一棵树的右树,对每个右树的遍历也是优先左树,再遍历右树,此时一个二叉树的前序遍历就完成了.

简单点说,就是前序遍历递归的root节点打印时间必须再两棵子树递归之前.

中序遍历

void inOrder(TreeNode root) {
        if (root == null) {
            return;
        }
        inOrder(root.left);
        System.out.print(root.val + " ");
        inOrder(root.right);
    }

中序遍历就是root的打印必须再左树遍历完成之后才能打印root,此时根节点在中间某一个位置.所以先不进行打印,将左树遍历完成之后在打印当下元素,此时的节点就是二叉树最后一层最左边的节点,然后返回到每棵子树依次打印其根节点,而后在对其右树进行相同的遍历,此时就完成了中序遍历.

后序遍历

void postOrder(TreeNode root) {
        if (root == null) {
            return;
        }
        postOrder(root.left);
        postOrder(root.right);
        System.out.print(root.val + " ");
    }

后序遍历就是将其左树右树全部遍历完成之后才能打印,此时根节点排在最后.

如果想通过遍历得到的结果来推测出二叉树的结构,那么必须要有两次不同的遍历结果,而且必须包含中序遍历,所以前序+中序  或者   中序+后序 可以推测出二叉树的结构.

层序遍历

    void levelOrder(TreeNode root) {
        Deque<TreeNode> deque = new LinkedList<>();
        if (root != null) {
            deque.add(root);
        }
        while (!deque.isEmpty()) {
            if (deque.peek().left != null) {
                deque.add(deque.peek().left);
            }
            if (deque.peek().right != null) {
                deque.add(deque.peek().right);
            }
            System.out.print(deque.pop().val + " ");
        }
    }

与前几种遍历方式不同,层序遍历就是对每一层进行逐层遍历打印.

那么我们得到root之后要做的两件事:   1.打印root    2.将root的两个孩子节点保存起来

而下一次循环我们需要 1.先调用root的左孩子打印,然后储存他的两个孩子节点,

2.调用右孩子打印,储存他的两个孩子节点.

依据层序遍历,上述遍历每个元素的顺序是不能够改变的.那么我们用什么来对节点进行储存呢?

那么依据每个元素先储存先打印,后储存,后打印的情况看,最优解就是队列了.

我们设计一个队列,先将根节点入队,然后进行while循环,只要队列不为空,就一直循环下去.此时如果root左树不为空,入队,右树不为空,入队,我们就完成了对其根节点的储存,此时我们将队列首元素也就是root弹出再进行打印,再进行下一次的循环,直到队列为空,我们就完成了对二叉树的层序遍历.

二叉树高度

    int getHeight(TreeNode root) {
        int l = 0;
        int r = 0;

        if (root == null) {
            return 0;
        }
        l = getHeight(root.left) ;
        r = getHeight(root.right);
        return l > r ? (l+1) : (r+1) ;
    }

树的高度为左树和右树中较高的一棵树的高度+1

那么此时我们就应该知道如何去写此代码,博主给出的实例如上.但是有一点值得注意,我们在比较的时候要设置一个变量,不要直接用递归结果进行比较,否则递归就会运行两次,大大增加运行负担.

二叉树叶子节点个数

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);

    }

二叉树叶子节点个数就是左子树叶子节点个数加上右子树叶子节点个数,叶子节点的判断,左右都为空.

二叉树节点数量

int size2(TreeNode root) {
        if (root == null) {
            return 0;
        }
        return size2(root.left) + size2(root.right) + 1;
    }

二叉树节点数量,首先是空树就return 0 如果不是的话就return其左树的节点个数+右树的节点个数+1(根节点自己)

判断二叉树是否为完全二叉树

void levelOrder(TreeNode root) {
        Deque<TreeNode> deque = new LinkedList<>();
        if (root != null) {
            deque.add(root);
        }
        while (!deque.isEmpty()) {
            if (deque.peek().left != null) {
                deque.add(deque.peek().left);
            }
            if (deque.peek().right != null) {
                deque.add(deque.peek().right);
            }
            System.out.print(deque.pop().val + " ");
        }
    }

最简单的方法就是将所有元素按照层序遍历放入队列,如果有null元素的话,就跳出循环,然后再将剩余元素全部弹出,若弹出结果全部为null则满足完全二叉树,否则不是.

第K层节点个数

 int getKLevelNodeCount(TreeNode root, int k) {
        if (root == null || k < 1) {
            return 0;
        }
        if (k == 1) {
            return 1;
        }
        return getKLevelNodeCount(root.left, k - 1) + getKLevelNodeCount(root.right, k - 1);
    }

第一次进来就是第一层的节点个数,此后每次递归k-1, 那么递归一次就是第二层,以此类推,当递归到k == 1的时候,此时就是我们所需要的层数,若此时的节点不为空就ruturn 1;二叉树第k层的节点个数就是其左右孩子第k-1层节点个数之和.

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值