攀爬二叉树,发现新的美

二叉树

什么是二叉树? 二叉树的基础概念? 性质? 问题?



一、二叉树的概念

(一)认识二叉树

二叉树是一种非线性的数据结构,
结点的度:一个结点含有子树的个数称为该结点的度
树的度:一棵树中,所有结点度的最大值称为树的度;
叶子结点:度为0的结点称为叶结点;
父结点:若一个结点含有子结点,则这个结点称为其子结点的父结点;
孩子子结点:一个结点含有的子树的根结点称为该结点的子结点;
根结点:一棵树中,没有双亲结点的结点;
结点的层次:从根开始定义起,根为第1层,根的子结点为第2层,以此类推
树的高度或深度:树中结点的最大层次;
在这里插入图片描述
满二叉树:一棵二叉树,如果每层的结点数都达到最大值,则这棵二叉树就是满二叉树
完全二叉树:完全二叉树是效率很高的数据结构,完全二叉树是由满二叉树而引出来的

在这里插入图片描述

(二)二叉树的性质

1.对任何一棵二叉树, 如果其叶结点个数为 n0, 度为2的非叶结点个数为 n2,则有n0=n2+1
推导:

在这里插入图片描述
2. 具有n个结点的完全二叉树的深度k为log2(n+1)上取整
3.对于具有n个节点完全二叉树,如果从上至下 从左到右的顺序对所有节点从0开始编号
则对于序号为i的结点有:

  • 若 i > 0,双亲序号为 (i-1)/2: i 为 0 时 ,i为根结点.
  • 若 2i+1<n,左孩子序号为2i + 1 否则无左孩子
  • 若 2i+2<n,右孩子序号为2i + 2 否则无右孩子

二、遍历二叉树

以这颗二叉树为栗子
在这里插入图片描述
实例化节点的对象并且创建二叉树

public class binaryTree {
    class TreeNode{
        public char val;
        private TreeNode left;
        private TreeNode right;

        public TreeNode(char val){
            this.val = val;
        }
    }
    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');
        TreeNode G = new TreeNode('G');
        TreeNode H = new TreeNode('H');

        A.left = B;
        B.left = D;
        B.right = E;
        E.right = H;
        A.right = C;
        C.left = F;
        C.right = G;
        return A;
    }
    }

遍历方式分为两种 1.递归遍历 2.非递归遍历
递归遍历:把问题拆分成子问题,判断结束条件和执行的代码

    每次递归时 判断该节点是否为空 作用:
    1.避免空指针异常
    2.为空时就返回 执行下一步操作

1.前序遍历

递归

	
public void preOrder(TreeNode root){
      
        if(root==null){
            return;
        }
        //打印
        System.out.print(root.val+" ");
        //遍历左子树
        preOrder(root.left);
		//遍历右子树
        preOrder(root.right);
    }

非递归
在这里插入图片描述

 public List<Character> preOrderNot(TreeNode root){
        List<Character> list = new ArrayList<>();
        Stack<TreeNode> s = new Stack<>();
        TreeNode cur = root;
        while (cur!=null || !s.empty()) {
            while(cur!=null){
                s.push(cur);
                list.add(cur.val);

                cur = cur.left;
            }
            TreeNode top = s.pop();
            cur = top.right;
        }
        return list;
    }

2.中序遍历

递归

 public void inOrder(TreeNode root){
        if(root ==null){
            return;
        }
        inOrder(root.left);
        /*打印之前 需要把递归每一个的左子树,直到左为空
          然后才能打印  , 在递归此时的右子树 不断循环
        */
        System.out.print(root.val +" ");
        inOrder(root.right);
    }

非递归

public List<Character> inOrderNot(TreeNode root){
        List<Character> list = new ArrayList<>();
        Stack<TreeNode> s = new Stack<>();
        TreeNode cur = root;
        while (cur!=null || !s.empty()) {
            while(cur!=null){
                s.push(cur);
                cur = cur.left;
            }
            TreeNode top = s.pop();
            list.add(top.val);
            cur = top.right;


        }
        return list;
    }

3.后序遍历

递归

  public void postOrder(TreeNode root){
        if(root==null){
            return;
        }
        postOrder(root.left);
        postOrder(root.right);

        System.out.print(root.val+" ");
    }

非递归

public List<Character> postOrderNot(TreeNode root){
        List<Character> list = new ArrayList<>();
        Stack<TreeNode> s = new Stack<>();
        TreeNode cur = root;
        TreeNode prev = null;
        while (cur!=null || !s.empty()) {
            while(cur!=null){
                s.push(cur);
                cur = cur.left;
            }
            TreeNode top = s.peek();
            if(top.right==null || top.right == prev){
                s.pop();
                list.add(top.val);
                prev = top;
            }else {
                cur = top.right;
            }
        }
        return list;
    }

4.层序遍历

层序遍历用递归实现是不能的,因为每一层的相邻节点没有直接的关系.
所以只能用非递归,那么非递归需要如何实现呢?
此时就要借助于队列
此时来个动画演示
在这里插入图片描述

  //层序遍历
    public void levelOrder(TreeNode root){
        if(root ==null){
            return;
        }
        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root);
        while (!queue.isEmpty()){
            TreeNode cur = queue.poll();
            System.out.print(cur.val+" ");
            if(cur.left!=null){
                queue.offer(cur.left);
            }
            if(cur.right!=null){
                queue.offer(cur.right);
            }
        }
    }

同时再刷下力控上的层序遍历

 public List<List<Integer>> levelOrder(TreeNode root) {
        List<List<Integer>> ret = new ArrayList<>();
        if(root == null){
            return ret;
        }
        Queue<TreeNode> q  = new LinkedList<>();
        q.offer(root);
        while(!q.isEmpty()){
            int size = q.size();
            List<Integer> list = new ArrayList<>();
            while(size>0){
                TreeNode cur = q.poll();
                list.add(cur.val);
                if(cur.left!=null){
                    q.offer(cur.left);
                }
                if(cur.right!=null){
                    q.offer(cur.right);
                }
                size--;
            }
            ret.add(list);
        }
        return ret;
    }

在这里插入图片描述

三丶创建二叉树

问题描述:编一个程序,读入用户输入的一串先序遍历字符串,根据此字符串建立一个二叉树(以指针方式存储)。 例如如下的先序遍历字符串: ABC##DE#G##F### 其中“#”表示的是空格,空格字符代表空树。建立起此二叉树以后,再对二叉树进行中序遍历,输出遍历结果。
题目源自于二叉树遍历

import java.util.Scanner;
//new一个节点
class TreeNode{
    public char val;
    public TreeNode left;
    public TreeNode right;
    
    public TreeNode(char val){
        this.val = val;
    }
}
// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
	//成员变量 避免递归时出现容错	
	/*
		根据先序字符串来创建二叉树,首先就要先遍历每一个字符,
		每遍历一个不为null('#')的时候都要创建一个节点,
		再不断进行i++操作 遇到字符为空时 就可以根据递归来连接每一个节点
	*/
    public static int i = 0;
    public static TreeNode createTree(String s){
        char[] ch = s.toCharArray();
        TreeNode root = null;
        if(ch[i]!='#'){
            root = new TreeNode(ch[i]);
            i++;
            root.left = createTree(s);
            root.right = createTree(s);
        }else{
            i++;
        }

        return root;
    }
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        // 注意 hasNext 和 hasNextLine 的区别
        while (in.hasNextLine()) { // 注意 while 处理多个 case
            String s = in.nextLine();
            TreeNode root = createTree(s);
            inOrder(root);
        }
    }
    //中序遍历
    public static void inOrder(TreeNode root){
        if(root==null){
            return;
        }
        inOrder(root.left);
        System.out.print(root.val+" ");
        inOrder(root.right);
    }
}

总结

提示:这里对文章进行总结:
二叉树的基础大概这些内容,这些代码一定要多理解,多敲 才能更进一步,二叉树较不易理解的内容还未更新,等下次复习的时候再更新~

  • 35
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值