二叉树(二)

本文介绍了一种使用非递归方式遍历二叉树的方法,并通过具体实例展示了先序、中序和后序遍历的过程及结果。文章还详细解释了栈在非递归遍历中的应用。

上一篇文章用了递归方式遍历二叉树,而这次将使用非递归方式遍历二叉树。


还是以以下例子:

 

(图片来自网上)

程序的代码参考于:http://robinsoncrusoe.iteye.com/blog/808526

package com.jian.tree;

import java.util.Stack;

public class BinaryTree02 {
   public static void main(String[] args) {
	  Tree root = init('A') ;//初始化根节点
	  
	  insertNode(root, 'A' , 'B') ; //添加节点
	  insertNode(root, 'B' , 'C') ;
	  insertNode(root, 'B' , 'D') ;
	  insertNode(root, 'D' , 'E') ;
	  insertNode(root, 'D' , 'F') ;
	  insertNode(root, 'E' , 'G') ;
	  
	  System.out.print("先序遍历的结果是:") ;
	  DLR(root) ; 
	  System.out.println();
	  System.out.print("中序遍历的结果是:") ;
	  LDR(root) ;
	  System.out.println();
	  System.out.print("后序遍历的结果是:") ;
	  LRD(root) ;
	  System.out.println();
//	  System.out.println("树的深度为:" + getDepth(root));
   }
   
   
   //树的初始化,添加节点,查找节点
   public static Tree init(char data){ //初始化这个二叉树
	   Tree root = new Tree() ;
	   root.setData(data) ; //根的数值
	   root.setLeft(null) ; //暂时设为null
	   root.setRight(null) ;//暂时设为null
	   
	   return root ;
   }
   
   public static void insertNode(Tree tree , char key , char value){
	   //key是父节点
	   //value是将要添加的节点的值
	   Tree parent = null ;
	   Tree node = null ;  
	  
	   parent = findNode(tree, key) ;
	   if(parent==null){
		   System.out.println("错误:未找到父节点") ;
		   node = null ;
		   return ;
	   }
	   node = new Tree() ;//创建一个新的节点
	   node.setData(value) ;
	   node.setLeft(null) ;
	   node.setRight(null) ;
	   
	   if(parent.getLeft()==null){ //左子树为空,则添加到左子树
		   parent.setLeft(node) ;
	   }else if(parent.getRight()==null){//右子树为空,则添加到右子树
		   parent.setRight(node) ;
	   }else return ;
   }
   
   public static Tree findNode(Tree tree , char key){  //根据key查找父节点
	   Tree parent ;
	   if(tree==null){
		   return null ;
	   }else {
		   if(tree.getData()==key){
			   return tree ;
		   }
		   else {
		       if((parent=findNode(tree.getLeft(), key))!=null){  //递归查找
			      return parent ;
		       }else if((parent=findNode(tree.getRight(), key))!=null){
			      return parent ;
		       }
		    else {
			   return null;
		    }
	   }
	   }
   }
   
   
   //-------------------------------------------树的遍历(使用非递归的方式)
   
   
   public static void DLR(Tree tree){            //先序遍历(非递归)
	   Stack<Tree> stack = new Stack<Tree>() ;   //定义二叉树节点栈
	   
	   if(tree!=null){
		   stack.push(tree) ;                    //根节点进栈
		   while(!stack.empty()){                //只要栈不空则继续循环
			   tree = stack.pop() ;              //取出刚才进栈的节点
			   System.out.print(tree.getData() + " ") ;  //输出节点
			  
			   //-------------------------------
			   //这里是右节点先入栈,左子树后入栈
			   //出栈时左子树先出栈,右子树后出栈
			   if(tree.getRight()!=null){
				   stack.push(tree.getRight()) ;
			   }
			   if(tree.getLeft()!=null){
				   stack.push(tree.getLeft()) ;
			   }
			   
		   }
	   }
	   
   }
   public static void LDR(Tree tree){           //中序遍历(非递归)
	   Stack<Tree> stack = new Stack<Tree> () ;
		   while(tree!=null||stack.size()>0){     
			   while(tree!=null){
				   stack.push(tree) ;         //左子树进栈
			       tree = tree.getLeft() ;
			   }
			   if (stack.size() > 0) {  
	                tree = stack.pop();  
	                System.out.print(tree.getData() + " ") ;
	                tree = tree.getRight();  
	            }  
		   }
   }
   
   public static void LRD(Tree tree){           //后续遍历(非递归)
	   Tree temp = tree ;                       //定义一个临时对象
	   Stack<Tree> stack = new Stack<Tree>() ;   
	   while(tree!=null){                
	       while(tree.getLeft() != null){ //用循环找到左子树
		       stack.push(tree) ;         //左子树进栈
		       tree = tree.getLeft() ;
		     
	       }
	   
	       while(tree!=null&&(tree.getRight()==null||tree.getRight() == temp)){
		       System.out.print(tree.getData() + " ") ;   //遍历节点
		       temp = tree ;
		       if(stack.empty()){
			      return ;
		        }
		       tree = stack.pop() ;  //返回上一个节点
	       }
	   
	       stack.push(tree) ;
	       tree = tree.getRight() ;
       }
   }
   
}


class Tree{
	 private char data ;  //节点数据
	 private Tree left ;  //左子树
	 private Tree right ; //右子树
	public char getData() {
		return data;
	}
	public void setData(char data) {
		this.data = data;
	}
	public Tree getLeft() {
		return left;
	}
	public void setLeft(Tree left) {
		this.left = left;
	}
	public Tree getRight() {
		return right;
	}
	public void setRight(Tree right) {
		this.right = right;
	}
	 
	 
}
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

运行结果是:

先序遍历的结果是:A B C D E G F
中序遍历的结果是:C B G E D F A
后序遍历的结果是:C G E F D B A
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

下面做一个简单分析(在下不才,分析可能会很多错):

相对于递归遍历,非递归遍历相对复杂得比较多,我们使用栈来进行非递归遍历。


先序遍历:

栈的进出情况:
Stack:[A)

Stack:[B)

Stack:[D,C)

Stack:[D)

Stack:[F,E)

Stack:[F,G)

Stack:[F)

--------------------------------------------

中序遍历:

Stack:[A,B,C)

Stack:[A,B)

Stack:[A,D,E,G)

Stack:[A,D,E)

Stack:[A,D)

Stack:[A,F)

Stack:[A)

-------------------------------------------

后序遍历

Stack:[A,B)

Stack:[A,B,D,E)

Stack:[A,B,D)

Stack:[A,B,D)

Stack:[A,B)

Stack:[A)

Stack:[)


内容概要:本文系统介绍了算术优化算法(AOA)的基本原理、核心思想及Python实现方法,并通过图像分割的实际案例展示了其应用价值。AOA是一种基于种群的元启发式算法,其核心思想来源于四则运算,利用乘除运算进行全局勘探,加减运算进行局部开发,通过数学优化器加速函数(MOA)和数学优化概率(MOP)动态控制搜索过程,在全局探索与局部开发之间实现平衡。文章详细解析了算法的初始化、勘探与开发阶段的更新策略,并提供了完整的Python代码实现,结合Rastrigin函数进行测试验证。进一步地,以Flask框架搭建前后端分离系统,将AOA应用于图像分割任务,展示了其在实际工程中的可行性与高效性。最后,通过收敛速度、寻优精度等指标评估算法性能,并提出自适应参数调整、模型优化和并行计算等改进策略。; 适合人群:具备一定Python编程基础和优化算法基础知识的高校学生、科研人员及工程技术人员,尤其适合从事人工智能、图像处理、智能优化等领域的从业者;; 使用场景及目标:①理解元启发式算法的设计思想与实现机制;②掌握AOA在函数优化、图像分割等实际问题中的建模与求解方法;③学习如何将优化算法集成到Web系统中实现工程化应用;④为算法性能评估与改进提供实践参考; 阅读建议:建议读者结合代码逐行调试,深入理解算法流程中MOA与MOP的作用机制,尝试在不同测试函数上运行算法以观察性能差异,并可进一步扩展图像分割模块,引入更复杂的预处理或后处理技术以提升分割效果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值