二叉树
什么是二叉树? 二叉树的基础概念? 性质? 问题? 
文章目录
- 二叉树
- 一、二叉树的概念
- (一)认识二叉树
- (二)二叉树的性质
 
- 二、遍历二叉树
- 1.前序遍历
- 2.中序遍历
- 3.后序遍历
- 4.层序遍历
 
- 三丶创建二叉树
- 总结
一、二叉树的概念
(一)认识二叉树
二叉树是一种非线性的数据结构,
 结点的度:一个结点含有子树的个数称为该结点的度
 树的度:一棵树中,所有结点度的最大值称为树的度;
 叶子结点:度为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);
    }
}
总结
提示:这里对文章进行总结:
 二叉树的基础大概这些内容,这些代码一定要多理解,多敲 才能更进一步,二叉树较不易理解的内容还未更新,等下次复习的时候再更新~



















