二叉树的非递归遍历算法 - 树结构 | 第2篇【java实现】

遍历是树结构算法中的重要部分,前面发了有关递归遍历的内容,要知道:递归就是函数调用函数本身,运行起来就是函数嵌套函数,层层嵌套,所以函数调用、参数堆栈都是不小的开销,但是程序简单。然而,非递归即不断地对参数入栈、出栈,省去了函数层层展开、层层调用的开销。虽然参数出入栈次数多了,但是一般都开辟固定的足够大的内存来一次性开辟、重复使用。

目录

一、 先序遍历(非递归) 

遍历步骤

直接上代码

二、 中序遍历(非递归) 

遍历步骤

直接上代码

三、 后序遍历(非递归) 

遍历步骤

直接上代码


一、 先序遍历(非递归) 

遍历步骤

先序遍历的最终访问次序是:根 - 左 - 右 ,具体步骤如下:

1. 设有一棵如下结构的树,并申请一个栈stack,用于存放树结点;

        

2. 将根节点'1'(如果有的话)入栈; 

        

 3. 以下操作为一个循环,注:入栈时 先右后左

        while(stack不为空){
              从栈中弹出一个栈顶元素root; 
              访问该结点root;(本例中将此添加到res数组中)

              if (root结点有右儿子)
                  将右儿子结点入栈; 
              if (root结点有左儿子)
                  将左儿子结点入栈;
        }

         

         

        

        

         

        

         stack栈为空,循环结束,先序遍历完毕!

 直接上代码

// 非递归先序遍历:	
public  void PreOrderTraversalNoRecursive(TreeNode root){
    	if (root != null) {
    		Stack<TreeNode> stack = new Stack<>();
    		stack.add(root);	
    		while(!stack.isEmpty()) {
    		    root = stack.pop();
        		Vist(root);
        		if(root.Rchild != null) {
    			stack.push(root.Rchild);
    			}
        		if(root.Lchild != null) {
        		 stack.push(root.Lchild);
    			}
    		}
        }
    }

二、 中序遍历(非递归) 

遍历步骤

中序遍历的最终访问次序是:左 - 根 - 右 ,具体步骤如下:

1. 设有一棵如下结构的树,并申请一个栈stack,用于存放树结点;

 2. 以下操作为一个循环,

        while(stack不为空 ){
              if (当前结点head不为空) :
                   head结点入栈; head = head.left;

              else:
                  head = 栈顶出栈; 
                  访问该结点head;(本例中将此添加到res数组中)
                  head = head.right;
        }

         

        

        

        

        

         stack1栈为空,循环结束,中序遍历完毕!

 直接上代码

// 非递归中序遍历:     
public  void InOrderTraversalNoRecursive(TreeNode head){
    	if (head != null) {
    		Stack<TreeNode> stack = new Stack<>();
    		while(!stack.isEmpty() || head!=null) {
    			if(head != null) {
    				stack.push(head);
    				head = head.Lchild;
    			}else {
    				head = stack.pop();
    				Vist(head);
    				head = head.Rchild;
    			}
    		}
        }
 }

三、 后序遍历(非递归) 

遍历步骤

后序遍历的最终访问次序是:左 - 右 - 根 ,具体步骤如下:

1. 设有一棵如下结构的树,并申请两个栈s1用于临时存放树结点、s2_res用于存放最终结点序列;

2. 将根节点'1'(如果有的话)入栈; 

        

 3. 以下操作为一个循环,注:s1入栈时 先左后右

        while(stack不为空) {
              从栈中弹出一个栈顶元素root; 
              访问该结点root;(本例中将此压入到s2_res栈中)

              if (root结点有左儿子)
                  将左儿子结点入栈;

              if (root结点有右儿子)
                  将右儿子结点入栈; 
        }

        

        

        

        

        

        

         最后将s2所有结点出栈:4 ,5 ,2 ,6 ,7 ,3 ,1 ; 即为后序遍历序列。

直接上代码

// 非递归后序遍历:
public  void PostOrderTraversalNoRecursive(TreeNode root){
    	if (root != null) {
    		Stack<TreeNode> s1 = new Stack<>();// 操作栈
    		Stack<TreeNode> s2 = new Stack<>();// 收集栈
    		s1.add(root);	
    		while(!s1.isEmpty()) {
    			root = s1.pop();
    			s2.push(root);
        		if(root.Lchild != null) {
        			s1.push(root.Lchild);
    			}
        		if(root.Rchild != null) {
    				s1.push(root.Rchild);
    			}
    		}
    		while(!s2.isEmpty()) {
        		Vist(s2.pop());
    		}
        }

    }

猜你喜欢

转载自blog.csdn.net/kndjg/article/details/126290142