数据结构之二叉树前序&中序&后序&层次遍历&递归与迭代实现


以下为Leecode的题以及参考大神做法

递归模板


    public void traverse(TreeNode root,List<Integer> last){
    	if(root==null)//如果为null代表最后的子节点,结束循环
    		return;
    	last.add(root.val);//代表根节点,将根节点作为标志,这条语句的位置决定是前序,中序还是后序,在left,right的前面就是前序,在left,right的中面就是中序,在left,right的后面就是后序
    	traverse(root.left,last);//左子树继续递归
    	traverse(root.right,last);//左子树继续递归
    }

迭代模板(前,中序)

将所有的左节点全部压入栈中,然后右节点,重复:把右节点的所有的左节点继续压入栈中,不断套娃

class Solution {
    public List<Integer> postorderTraversal(TreeNode root) {
		if(root==null)
			return new ArrayList<>();
        List<Integer> last= new ArrayList<>();
        Stack<TreeNode> stack =new Stack<>();
        while(true){//不断进行循环,重复
        while(root!=null){
        	stack.push(root);
        	last.add(root.val);//此条语句决定前,中序遍历,在left前面为前序
        	root=root.left;//不断将左节点压入栈中
        }
        if(stack.isEmpty())//当栈为空代表根节点(第一个入栈的,最后出的)都遍历了,已经全部遍历完了
        	break;
        TreeNode node = stack.pop();//出栈,向上一节点继续遍历
        root=node.right;
        }
    
    return last;
    }
}

以下的TreeNode都以此为结构

 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }

一:前序遍历

前序遍历:根–>左–>右

递归实现

class Solution {
    public List<Integer> postorderTraversal(TreeNode root) {

        List<Integer> last = new ArrayList<>();
    	traverse(root,last);
        return last;
    }
    public void traverse(TreeNode root,List<Integer> last){
    	if(root==null)//如果为null代表最后的子节点都遍历了,结束循环
    		return;
    	last.add(root.val);//将根节点的数据添加到列表
    	traverse(root.left,last);//左子树继续递归
    	traverse(root.right,last);//左子树继续递归
    }
}

迭代遍历

利用栈的我们先将所有的左节点压入栈,在压入完一个分支的所有左节点前先遍历当前根节点,然后出栈,然后遍历右节点

class Solution {
    public List<Integer> postorderTraversal(TreeNode root) {
		if(root==null)
			return new ArrayList<>();
        List<Integer> last= new ArrayList<>();
        Stack<TreeNode> stack =new Stack<>();
        while(true){
        while(root!=null){//将左子树的所有左节点压入栈
        	stack.push(root);
        	last.add(root.val);
        	root=root.left;
        }
        if(stack.isEmpty())//如果为空,则表明已经到了根节点都已经遍历过了,该结束了
        	break;
        TreeNode node = stack.pop();//出栈后下面进行右子树的遍历
        root=node.right;
        }
    
    return last;
    }
}

二:中序遍历

左->根->右

递归实现

class Solution {
    public List<Integer> postorderTraversal(TreeNode root) {

        List<Integer> last= new ArrayList<>();
    	traverse(root,last);
        return last;
    }
    public void traverse(TreeNode root,List<Integer> last){
    	if(root==null)//如果为null代表最后的子节点,结束循环
    		return;
    	traverse(root.left,last);//左子树继续递归
    	last.add(root.val);//将根节点的数据添加到列表
    	traverse(root.right,last);//右子树继续递归
    }
}

迭代实现

利用栈的我们先将所有的左节点压入栈,在压入完一个分支的所有左节点后,然后出栈,遍历当前根节点,然后遍历右节点

class Solution {
    public List<Integer> postorderTraversal(TreeNode root) {
		if(root==null)
			return new ArrayList<>();
        List<Integer> last= new ArrayList<>();
        Stack<TreeNode> stack =new Stack<>();
        while(true){
        while(root!=null){
        	stack.push(root);
        	root=root.left;
        }
        if(stack.isEmpty())
        	break;
        TreeNode node = stack.pop();
        last.add(node.val);//遍历根节点
        root=node.right;
        }
    
    return last;
    }
}

三:后序遍历

左->右->根,后序比较难一些,需要判断是否已经将右子树遍历,需要记录前一个节点的信息~,如果没有需要进行遍历才能进行根节点的处理

递归实现

class Solution {
    public List<Integer> postorderTraversal(TreeNode root) {

        List<Integer> last= new ArrayList<>();
    	traverse(root,last);
        return last;
    }
    public void traverse(TreeNode root,List<Integer> last){
    	if(root==null)//如果为null代表最后的子节点,结束循环
    		return;
    	traverse(root.left,last);//左子树继续递归
    	traverse(root.right,last);//右子树继续递归
    	last.add(root.val);//将根节点的数据添加到列表
    }
}

迭代遍历

class Solution {
    public List<Integer> postorderTraversal(TreeNode root) {
		if(root==null)
			return new ArrayList<>();
        List<Integer> res = new ArrayList<>();
        Stack<TreeNode> stack =new Stack<>();
		TreeNode pre=null;//作为当前前面一个节点,用来后面判断右子树是否遍历完
        while(root!=null){//将所有的左子树压入栈中
        	pre =root;
        	stack.push(root);
        	root=root.left;
        }
        
        while(!stack.isEmpty()){
        	TreeNode node = stack.peek();//取当前栈顶
      	 	if(pre==node.right||node.right==null){//当在一棵树的最最最下层子节点时node.right为null,当不是最下层子节点时,pre等于上层节点的右子树,这两种情况时说明该节点的右子树已经遍历完~则左->右->根,该进行根的操作
      	 		pre=stack.pop();
      	 		last.add(node.val);
      	 	}else{
      	 	root=node.right;//如果没有遍历完右子树,则进行右子树遍历,如果该右子树还有孩子左子树,进行右子树的将所有的左子树压入栈
      	 	while(root!=null){//
				pre=root;
				stack.push(root);
				root=root.left;
			}
      	 }
        }
    return last;
  }
}

三:层次遍历

递归实现

该算法从一个根节点开始,首先访问节点本身。 然后遍历它的相邻节点,其次遍历它的二级邻节点、三级邻节点,以此类推。

当我们在树中进行广度优先搜索时,我们访问的节点的顺序是按照层序遍历顺序的。

class Solution {
    public List<List<Integer>> levelOrder(TreeNode root) {
        List<List<Integer>> last=new ArrayList<>();//用于存储每一层的数据,而每一层的数据就放在一个ArrayList里面,再把所有的放到一个list里面
        traverse(root,last,0);
        return last;

    }
    public void traverse(TreeNode root,List<List<Integer>> last,int level){//level用来表示当前的层数
        if(root==null)
            return;
        if(level==last.size())//当当前层数为list的大小时,增加一条为下文做准备
            last.add(new ArrayList<>());
        last.get(level).add(root.val);//通过level索引进行操作
        traverse(root.left,last,level+1);
        traverse(root.right,last,level+1);
    }
}

迭代实现

按照BFS的思想将一个节点出队时将它所有的子节点入队

 class Solution {
    public List<List<Integer>> levelOrder(TreeNode root) {
        if(root==null)
            return new ArrayList<>();
        List<List<Integer>> last=new ArrayList<>();
        Queue<TreeNode> queue =new LinkedList<>();//用来存储节点
        queue.add(root);
        while(!queue.isEmpty()){
            int n=queue.size();//用来表示root下面一层有多少个节点
            List<Integer> temp=new ArrayList<>();
            for(int i=0;i<n;i++){//用来遍历下层节点
                 TreeNode node =queue.remove();
                    temp.add(node.val);
                if(node.left!=null){//不为空则入列
                    queue.add(node.left);
                }
                if(node.right!=null){
                    queue.add(node.right);
                }
            }
          last.add(temp);
        }
     
        return last;

    }
}
发布了57 篇原创文章 · 获赞 5 · 访问量 2795

猜你喜欢

转载自blog.csdn.net/qq_43520913/article/details/105602303