需求

了解二叉树

解决

是什么

从根节点开始,小的向左边放,大的向右边放,一层一层放下去。满足左小右大原则。

  • 没有子节点的是叶子
  • 子节点的个数是度
  • 从根到当前节点的为一路径上节点总数是深度
  • 从当前节点到最远叶子路径上的节点总数是高度

用处

用于大数据量时的反复的搜索和插入。

  • 有序链表: 查找成本大 O(N), 插入成本小 O(1)
  • 有序数组: 查找成本小 O(1), 插入成本大 O(N)
  • 排序二叉树: 比较折中,查找时类似于二分查找 O(logN), 插入成本也小 O(logN).

打印

层序遍历

public int[] levelOrder(TreeNode root) {
      int arr[]=new int[10000];
      int index=0;
      Queue<TreeNode>queue=new ArrayDeque<>();
      if(root!=null)
	  queue.add(root);
      while (!queue.isEmpty()){
	  TreeNode node=queue.poll();
	  arr[index++]= node.val;
	  if(node.left!=null)
	      queue.add(node.left);
	  if(node.right!=null)
	      queue.add(node.right);

      }
      return Arrays.copyOf(arr,index);
    }

分层存储

public List<List<Integer>> levelOrder(TreeNode root) {
  List<List<Integer>>list=new ArrayList<List<Integer>>();
  if(root==null)return list;
  Queue<TreeNode>q1=new ArrayDeque<TreeNode>();
  q1.add(root);
  while (!q1.isEmpty()) {
    int size=q1.size();
    List<Integer>value=new ArrayList<Integer>();
    for(int i=0;i<size;i++)
    {
      TreeNode pNode=q1.poll();
      if(pNode.left!=null)
      q1.add(pNode.left);
      if(pNode.right!=null)
      q1.add(pNode.right);
      value.add(pNode.val);
    }
    list.add(value);
  }
  return list;
}

之字形打印

public List<List<Integer>> levelOrder(TreeNode root) {
  List<List<Integer>> value=new ArrayList<>();//存储到的最终结果
  if(root==null)
    return value;
  int index=0;//判断
  Queue<TreeNode>queue=new ArrayDeque<>();
  queue.add(root);
  while (!queue.isEmpty()){
    List<Integer>va=new ArrayList<>();//临时 用于存储到value中
    int len=queue.size();//当前层的数量
    for(int i=0;i<len;i++){
      TreeNode node=queue.poll();
      if(index%2==0)
      va.add(node.val);
      else
      va.add(0,node.val);
      if(node.left!=null)
      queue.add(node.left);
      if(node.right!=null)
      queue.add(node.right);
    }
    value.add(va);
    index++;
  }
  return value;
}

遍历

前序遍历

  • 递归

    class Solution {
        List<Integer>value=new ArrayList();
        public List<Integer> preorderTraversal(TreeNode root) {
          qianxu(root);
          return value;
        }
        private void qianxu(TreeNode node) {
          if(node==null)
    	  return;
          value.add(node.val);
          qianxu(node.left);
          qianxu(node.right);
        }
    }
    
  • 非递归

    class Solution {
      public List<Integer> preorderTraversal(TreeNode root) {
        List<Integer>value=new ArrayList();
        Stack<TreeNode> q1 = new Stack();
    	      while(!q1.isEmpty()||root!=null)
    	      {
    		      while (root!=null) {
    			      value.add(root.val);
    			      q1.push(root);
    			      root=root.left;
    		      }
    	  root=q1.pop();//抛出
    	  root=root.right;//准备访问其右节点
    
    	      }
          return value;
        }
    }
    

中序遍历

  • 递归

    class Solution {
       public List<Integer> inorderTraversal(TreeNode root) {
    	List<Integer>value=new ArrayList<Integer>();
    	zhongxu(root,value);
    	return value;
      }
           private void zhongxu(TreeNode root, List<Integer> value) {
    	       if(root==null)
    		       return;
    	       zhongxu(root.left, value);
    	       value.add(root.val);
    	       zhongxu(root.right, value);
    
          }
    }
    
  • 非递归

    class Solution {
       public List<Integer> inorderTraversal(TreeNode root) {
          List<Integer>value=new ArrayList<Integer>();
        Stack<TreeNode> q1 = new Stack();
        while(!q1.isEmpty()||root!=null)
        {
          while (root!=null) {
    	  q1.push(root);
    	  root=root.left;
          }
          root=q1.pop();//抛出
          value.add(root.val);
          root=root.right;//准备访问其右节点
    
        }
        return value;
      }
    }
    

后序遍历

  • 递归

    class Solution {
        List<Integer>value=new ArrayList<>();
        public List<Integer> postorderTraversal(TreeNode root) {
          houxu(root);
          return value;
        }
        private void houxu(TreeNode root) {
          if(root==null)
    	  return;
          houxu(root.left);
          houxu(root.right);//右子树回来
          value.add(root.val);
        }
    }
    
  • 非递归

    class Solution {
        public List<Integer> postorderTraversal(TreeNode root) {
          List<Integer> value=new ArrayList();
          Stack<TreeNode> q1 = new Stack();
          Map<TreeNode,Integer >map=new HashMap<>();
          while(!q1.isEmpty()||root!=null)
          {
    	  if (root!=null) {
    	      q1.push(root);
    	      map.put(root, 1); //t.value标记这个值节点出现的次数
    	      root=root.left;
    	  }
    	  else {
    	      root=q1.peek();
    	      if(map.get(root)==2) {//第二次访问,抛出
    		  q1.pop();
    		  value.add(root.val);
    		  root=null;//需要往上走
    	      }
    	      else {
    		  map.put(root, 2);
    		  root=root.right;
    	      }
    	  }
    	}
    	return value;
        }
    }
    
  • 非递归,防止 hash 冲突

    class Solution {
        public List<Integer> postorderTraversal(TreeNode root) {
          TreeNode temp=root;//枚举的临时节点
          List<Integer>value=new ArrayList<>();
          TreeNode pre=null;//前置节点
          Stack<TreeNode>stack=new Stack<>();
    
          while (!stack.isEmpty()||temp!=null){
    
    	  while(temp!=null){
    	      stack.push(temp);
    	      temp=temp.left;
    	  }
    	  temp=stack.pop();
    	  if(temp.right==pre||temp.right==null)//需要弹出
    	  {
    	      value.add(temp.val);
    	      pre=temp;
    	      temp=null;//需要重新从栈中抛出
    	  }else{
    	      stack.push(temp);
    	      temp=temp.right;
    	  }
    
          }
          return value;
        }
    }
    
  • 后序左右中,反向就是中右左,即反向前序

    class Solution {
        public List<Integer> postorderTraversal(TreeNode root) {
          List<Integer>value=new ArrayList();
          Stack<TreeNode> q1 = new Stack();
          while(!q1.isEmpty()||root!=null)
          {
          while (root!=null) {
    	value.add(root.val);
    	q1.push(root);
    	root=root.right;
          }
          root=q1.pop();//抛出
          root=root.left;//准备访问其右节点
          }
          Collections.reverse(value);//将结果翻转
          return value;
    
    
        }
    }
    

两个序列构造二叉树

前序和中序

class Solution {
    public List<Integer> postorderTraversal(TreeNode root) {
      List<Integer>value=new ArrayList();
      Stack<TreeNode> q1 = new Stack();
      while(!q1.isEmpty()||root!=null)
      {
      while (root!=null) {
	value.add(root.val);
	q1.push(root);
	root=root.right;
      }
      root=q1.pop();//抛出
      root=root.left;//准备访问其右节点
      }
      Collections.reverse(value);//将结果翻转
      return value;


    }
}

中序和后序

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
   public TreeNode buildTree(int[] inorder,int[] postorder) {
	      if(postorder.length==0)
		      return null;
	      Map<Integer, Integer>map=new HashMap<Integer, Integer>();
	      for(int i=0;i<inorder.length;i++)
	      {
		      map.put(inorder[i], i);
	      }
	      return buildTree(postorder,0,postorder.length-1, map,0,inorder.length-1);
    }

      private TreeNode buildTree(int[] postorder, int postStart, int postEnd, Map<Integer, Integer> map, int inStart, int inEnd) {
	      // TODO Auto-generated method stub
	      if(postEnd<postStart||inEnd<inStart)
		      return null;
	      TreeNode node=new TreeNode(postorder[postEnd]);
	      int i=map.get(postorder[postEnd])
	      int leftlen=i-inStart;
	      node.left=buildTree(postorder, postStart,postStart+leftlen-1, map, inStart, i-1);
	      node.right=buildTree(postorder, postStart+leftlen,postEnd-1, map, i+1, inEnd);
    return node;
      }
}

参考

一文彻底搞定二叉树的前序、中序、后序遍历(图解递归非递归)

二叉树的作用

彻底弄懂二叉树的先序、中序、后序三种遍历与做题

二叉树的前序、中序、后序遍历(个人笔记)

二叉树及其作用浅析

前序、中序、后续遍历二叉树

二叉树及其生活应用.ppt

如何学习数据结构?

图解:什么是B树?(心中有 B 树,做人要虚心)一文读懂B-树

Java中的ListNode和TreeNode类