热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

算法:二叉树的先(根)序遍历、中(根)序遍历、后(根)序遍历(递归及压栈出栈实现的非递归方式)的java代码实现

 首先来看一棵二叉树:1、前(根)序遍历,也叫先序遍历:前序遍历首先访问根结点然后遍历左子树,最后遍历右子树。在遍历左、右子树时,仍然先访问根结点,然后遍历左子树,最后遍历右子树。

 首先来看一棵二叉树:

《算法:二叉树的先(根)序遍历、中(根)序遍历、后(根)序遍历(递归及压栈出栈实现的非递归方式)的java代码实现》

1、前(根)序遍历,也叫先序遍历:

前序遍历首先访问根结点然后遍历左子树,最后遍历右子树。在遍历左、右子树时,仍然先访问
根结点,然后遍历左子树,最后遍历右子树。 若
二叉树为空则结束返回,否则: (1)访问根结点; (2)前序遍历左子树; (3)前序遍历右子树 ; 需要注意的是:遍历左右子树时仍然采用前序遍历方法。可以看出前序遍历后,遍历结果为:631254978
2、中(根)序遍历: 中序遍历首先遍历左子树,然后访问根结点,最后遍历右子树。在遍历左、右子树时,仍然先遍历左子树,再访问根结点,最后遍历右子树。即: 若
二叉树为空则结束返回,
否则: (1)中序遍历左子树; (2)访问根结点;

(3)中序遍历右子树; 注意的是:遍历左右子树时仍然采用中序遍历方法。最上图的二叉树用中序遍历的结果是:123456789
3、后(根)遍历: 后序遍历首先遍历左子树,然后遍历右子树,最后访问根结点,在遍历左、右子树时,仍然先遍历左子树,然后遍历右子树,最后遍历根结点。即: 若
二叉树为空则结束返回,
否则: (1)后序遍历左子树; (2)后序遍历右子树; (3)访问根结点; 如图所示的二叉树,用后序遍历的结果是:214538796

三种遍历的递归实现:
[java] 
view plain
 copy

  1. public class Node { //二叉树节点  
  2.       
  3.     private int data;  
  4.     private Node leftNode;  
  5.     private Node rightNode;  
  6.       
  7.     public Node(int data, Node leftNode, Node rightNode){  
  8.         this.data = data;  
  9.         this.leftNode = leftNode;  
  10.         this.rightNode = rightNode;  
  11.     }  
  12.       
  13.     public int getData(){  
  14.         return data;  
  15.     }  
  16.       
  17.     public void setData(int data){  
  18.         this.data = data;  
  19.     }  
  20.       
  21.     public Node getLeftNode(){  
  22.         return leftNode;  
  23.     }  
  24.       
  25.     public void setLeftNode(Node leftNode){  
  26.         this.leftNode = leftNode;  
  27.     }  
  28.       
  29.     public Node getRightNode(){  
  30.         return rightNode;  
  31.     }  
  32.       
  33.     public void setRightNode(Node rightNode){  
  34.         this.rightNode = rightNode;  
  35.     }  
  36.       
  37. }  

三种遍历的递归实现:
[java] 
view plain
 copy

  1. public class BinaryTree_DiGui {  
  2.       
  3.     /* 
  4.      * 二叉树先序中序后序排序 
  5.      * 方式:递归。 
  6.      */  
  7.       
  8.     //注意必须逆序简历,先建立子节点,再逆序往上建立,  
  9.     //因为非叶子节点会使用到下面的节点,而初始化是按顺序初始化得,不逆序建立会报错  
  10.     public static Node init(){  
  11.         Node J = new Node(8nullnull);  
  12.         Node H = new Node(4nullnull);  
  13.         Node G = new Node(2nullnull);  
  14.         Node F = new Node(7null, J);  
  15.         Node E = new Node(5, H, null);  
  16.         Node D = new Node(1null, G);  
  17.         Node C = new Node(9, F, null);  
  18.         Node B = new Node(3, D, E);  
  19.         Node A = new Node(6, B, C);  
  20.         return A;  //返回根节点  
  21.     }  
  22.       
  23.     //打印节点数值  
  24.     public static void printNode(Node node){  
  25.         System.out.print(node.getData());  
  26.     }  
  27.       
  28.       
  29.     //先序遍历  
  30.     public static void preOrder(Node root){  
  31.           
  32.         printNode(root);//打印根节点  
  33.           
  34.         if(root.getLeftNode() != null){ //使用递归遍历左孩子  
  35.             preOrder(root.getLeftNode());  
  36.         }  
  37.         if(root.getRightNode() != null){ //使用递归遍历右孩子  
  38.             preOrder(root.getRightNode());  
  39.         }  
  40.     }  
  41.       
  42.       
  43.     //中序遍历  
  44.     public static void inOrder(Node root){  
  45.           
  46.         if(root.getLeftNode() != null){ //使用递归遍历左孩子  
  47.             inOrder(root.getLeftNode());  
  48.         }  
  49.           
  50.         printNode(root);//打印根节点  
  51.           
  52.         if(root.getRightNode() != null){ //使用递归遍历右孩子  
  53.             inOrder(root.getRightNode());  
  54.         }  
  55.     }  
  56.       
  57.       
  58.     //后续遍历  
  59.     public static void postOrder(Node root){  
  60.           
  61.         if(root.getLeftNode() != null){ //使用递归遍历左孩子  
  62.             postOrder(root.getLeftNode());  
  63.         }  
  64.           
  65.         if(root.getRightNode() != null){ //使用递归遍历右孩子  
  66.             postOrder(root.getRightNode());  
  67.         }  
  68.           
  69.         printNode(root);//打印根节点  
  70.     }  
  71.       
  72.       
  73.     public static void main(String[] args){  
  74. //      BinaryTree tree = new BinaryTree();//注释掉本行后类中方法需变为static  
  75.         Node root = init();  
  76.           
  77.         System.out.println(“先序遍历”);  
  78.         preOrder(root);  
  79.         System.out.println(“”);  
  80.           
  81.         System.out.println(“中序遍历”);  
  82.         inOrder(root);  
  83.         System.out.println(“”);  
  84.           
  85.         System.out.println(“后序遍历”);  
  86.         postOrder(root);  
  87.         System.out.println(“”);  
  88.           
  89.     }  
  90.       
  91. }  

通过栈实现三种遍历(非递归):
[java] 
view plain
 copy

  1. public class BinaryTree_Zhan {  
  2.       
  3.     /* 
  4.      *  
  5.      * 二叉树先序中序后序排序 
  6.      * 方式:采用非递归方式。 
  7.      */  
  8.       
  9.     //注意必须逆序简历,先建立子节点,再逆序往上建立,  
  10.     //因为非叶子节点会使用到下面的节点,而初始化是按顺序初始化得,不逆序建立会报错  
  11.     public static Node init(){  
  12.         Node J = new Node(8nullnull);  
  13.         Node H = new Node(4nullnull);  
  14.         Node G = new Node(2nullnull);  
  15.         Node F = new Node(7null, J);  
  16.         Node E = new Node(5, H, null);  
  17.         Node D = new Node(1null, G);  
  18.         Node C = new Node(9, F, null);  
  19.         Node B = new Node(3, D, E);  
  20.         Node A = new Node(6, B, C);  
  21.         return A;  //返回根节点  
  22.     }  
  23.       
  24.     //打印节点数值  
  25.     public static void printNode(Node node){  
  26.         System.out.print(node.getData());  
  27.     }  
  28.       
  29.       
  30.     public static void preOrder_stack(Node root){ //先序遍历  
  31.           
  32.         Stack stack = new Stack();  
  33.         Node node = root;  
  34.           
  35.         while(node != null || stack.size()>0){ //将所有左孩子压栈  
  36.             if(node != null){ //压栈之前先访问  
  37.                 printNode(node);  
  38.                 stack.push(node);  
  39.                 node = node.getLeftNode();  
  40.                   
  41.             }else{  
  42.                 node = stack.pop();  
  43.                 node = node.getRightNode();  
  44.             }  
  45.         }  
  46.     }  
  47.       
  48.       
  49.     public static void inOrder_Stack(Node root){ //中序遍历  
  50.           
  51.         Stack stack = new Stack();  
  52.         Node node = root;  
  53.           
  54.         while(node != null || stack.size()>0){  
  55.             if(node != null){  
  56.                 stack.push(node);//直接压栈  
  57.                 node = node.getLeftNode();  
  58.             }else{  
  59.                 node = stack.pop();//出栈并访问  
  60.                 printNode(node);  
  61.                 node = node.getRightNode();  
  62.             }  
  63.         }  
  64.     }  
  65.       
  66.       
  67.     public static void postOrder_Stack(Node root){ //后续遍历  
  68.           
  69.         Stack stack = new Stack();  
  70.         Stack output = new Stack();//构造一个中间栈来存储逆后续遍历的结果  
  71.         Node node = root;  
  72.         while(node != null || stack.size()>0){  
  73.             if(node != null){  
  74.                 output.push(node);  
  75.                 stack.push(node);  
  76.                 node = node.getRightNode();  
  77.             }else{  
  78.                 node = stack.pop();  
  79.                 node = node.getLeftNode();  
  80.             }  
  81.         }  
  82.           
  83.         while(output.size()>0){  
  84.             printNode(output.pop());  
  85.         }  
  86.           
  87.     }  
  88.       
  89.       
  90.     public static void main(String[] args){  
  91.           
  92.         Node root = init();  
  93.           
  94.         System.out.println(“先序遍历”);  
  95.         preOrder_stack(root);  
  96.         System.out.println(“”);  
  97.           
  98.         System.out.println(“中序遍历”);  
  99.         inOrder_Stack(root);   
  100.         System.out.println(“”);  
  101.           
  102.         System.out.println(“后序遍历”);  
  103.         postOrder_Stack(root);  
  104.         System.out.println(“”);  
  105.     }  
  106.   
  107. }  

推荐阅读
  • 重入锁(ReentrantLock)学习及实现原理
    本文介绍了重入锁(ReentrantLock)的学习及实现原理。在学习synchronized的基础上,重入锁提供了更多的灵活性和功能。文章详细介绍了重入锁的特性、使用方法和实现原理,并提供了类图和测试代码供读者参考。重入锁支持重入和公平与非公平两种实现方式,通过对比和分析,读者可以更好地理解和应用重入锁。 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • Java太阳系小游戏分析和源码详解
    本文介绍了一个基于Java的太阳系小游戏的分析和源码详解。通过对面向对象的知识的学习和实践,作者实现了太阳系各行星绕太阳转的效果。文章详细介绍了游戏的设计思路和源码结构,包括工具类、常量、图片加载、面板等。通过这个小游戏的制作,读者可以巩固和应用所学的知识,如类的继承、方法的重载与重写、多态和封装等。 ... [详细]
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • 阿,里,云,物,联网,net,core,客户端,czgl,aliiotclient, ... [详细]
  • 本文介绍了OC学习笔记中的@property和@synthesize,包括属性的定义和合成的使用方法。通过示例代码详细讲解了@property和@synthesize的作用和用法。 ... [详细]
  • JavaSE笔试题-接口、抽象类、多态等问题解答
    本文解答了JavaSE笔试题中关于接口、抽象类、多态等问题。包括Math类的取整数方法、接口是否可继承、抽象类是否可实现接口、抽象类是否可继承具体类、抽象类中是否可以有静态main方法等问题。同时介绍了面向对象的特征,以及Java中实现多态的机制。 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • 个人学习使用:谨慎参考1Client类importcom.thoughtworks.gauge.Step;importcom.thoughtworks.gauge.T ... [详细]
  • 本文详细介绍了Java中vector的使用方法和相关知识,包括vector类的功能、构造方法和使用注意事项。通过使用vector类,可以方便地实现动态数组的功能,并且可以随意插入不同类型的对象,进行查找、插入和删除操作。这篇文章对于需要频繁进行查找、插入和删除操作的情况下,使用vector类是一个很好的选择。 ... [详细]
  • [大整数乘法] java代码实现
    本文介绍了使用java代码实现大整数乘法的过程,同时也涉及到大整数加法和大整数减法的计算方法。通过分治算法来提高计算效率,并对算法的时间复杂度进行了研究。详细代码实现请参考文章链接。 ... [详细]
  • 模板引擎StringTemplate的使用方法和特点
    本文介绍了模板引擎StringTemplate的使用方法和特点,包括强制Model和View的分离、Lazy-Evaluation、Recursive enable等。同时,还介绍了StringTemplate语法中的属性和普通字符的使用方法,并提供了向模板填充属性的示例代码。 ... [详细]
  • 欢乐的票圈重构之旅——RecyclerView的头尾布局增加
    项目重构的Git地址:https:github.comrazerdpFriendCircletreemain-dev项目同步更新的文集:http:www.jianshu.comno ... [详细]
  • 本文介绍了在MFC下利用C++和MFC的特性动态创建窗口的方法,包括继承现有的MFC类并加以改造、插入工具栏和状态栏对象的声明等。同时还提到了窗口销毁的处理方法。本文详细介绍了实现方法并给出了相关注意事项。 ... [详细]
  • HashMap的相关问题及其底层数据结构和操作流程
    本文介绍了关于HashMap的相关问题,包括其底层数据结构、JDK1.7和JDK1.8的差异、红黑树的使用、扩容和树化的条件、退化为链表的情况、索引的计算方法、hashcode和hash()方法的作用、数组容量的选择、Put方法的流程以及并发问题下的操作。文章还提到了扩容死链和数据错乱的问题,并探讨了key的设计要求。对于对Java面试中的HashMap问题感兴趣的读者,本文将为您提供一些有用的技术和经验。 ... [详细]
author-avatar
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有