大话数据结构(七)——二叉树创建与遍历(递归、非递归)的java实现
来源:互联网 发布:微盘交易平台源码出售 编辑:程序博客网 时间:2024/05/24 23:15
什么是二叉树呢?二叉树是n(n>=0)个结点的有限组合,该集合或者为空集,或者由一个根结点和两棵互不相交的、分别称为根结点的左子树和右子树的二叉树组成。二叉树的具体结构如下图所示:
二叉树的遍历这里介绍三种方法:前序遍历,中序遍历和后序遍历。
前序遍历:前序遍历的规则是若二叉树为空,则空操作返回,否则先访问根结点,然后前序遍历左子树,再遍历右子树。若前序遍 历上图中的树,则遍历顺序为:ABDECFG
中序遍历:中序遍历的规则是若二叉树为空,则空操作返回,否则根结点开始(但并不是先访问根结点),中序遍布根结点的左子 树,然后是访问根结点,最后遍历右子树。若中序遍历上图中的树,则遍历顺序为:DBEAFCG
后序遍历:后序遍历的规则是若二叉树为空,则空操作返回,否则从左到右先叶子后结点的方式遍历访问左右子树,最后是访问根 结点。若后序遍历上图中的树,则遍历顺序为:DEBFGCA
下面的程序实现了创建一棵二叉树,并使用了递归和非递归的方法对这个二叉树进行了前序遍历,中序遍历和后序遍历。
二叉树创建和遍历的实现方法
package BinaryTree;import java.util.Stack;/** * Created by jiangxs on 17-5-29. */public class BinaryTree { //创建二叉树的结点 public class TreeNode<T>{ private T data;//结点数据 private TreeNode leftChild;//左孩子指针 private TreeNode rightChild;//右孩子指针 //空构造器 public TreeNode(){} //含结点数据的构造器 public TreeNode(T data){ this.data = data; } //新结点含结点数据并以leftChild结点为左孩子,rightChild结点为右孩子 public TreeNode(T data,TreeNode leftChild,TreeNode rightChild){ this(data); this.leftChild = leftChild; this.rightChild = rightChild; } public T getData(){ return data; } public void setData(T data){ this.data = data; } public TreeNode getLeftChild(){ return leftChild; } public void setLeftChild(TreeNode leftChild){ this.leftChild = leftChild; } public TreeNode getRightChild(){ return rightChild; } public void setRightChild(TreeNode rightChild){ this.rightChild = rightChild; } } /** * 创建一棵二叉树 * A * B C * D E F G */ public TreeNode creatBinTree(){ //初始化各个结点,并对各个结点关联各自的左右孩子 TreeNode rootLeftLeft = new TreeNode("D",null,null); TreeNode rootLeftRight = new TreeNode("E",null,null); TreeNode rootRightLeft = new TreeNode("F",null,null); TreeNode rootRightRight = new TreeNode("G",null,null); TreeNode rootLeft = new TreeNode("B",rootLeftLeft,rootLeftRight); TreeNode rootRight = new TreeNode("C",rootRightLeft,rootRightRight); TreeNode root = new TreeNode("A",rootLeft,rootRight); return root; } /** * 前序遍历法 * 递归版本 */ public void recursePreOrderTraverse(TreeNode root){ if (root == null) return; System.out.println("当前结点数据: "+root.getData()); recursePreOrderTraverse(root.leftChild); recursePreOrderTraverse(root.rightChild); } /** * 前序遍历法 * 非递归版本 */ public void preOrderTraverse(TreeNode root){ //若根结点为空则直接结束 if (root == null) return; //初始化用于存放结点顺序的栈结构 Stack<TreeNode> stack = new Stack<TreeNode>(); //首先将根结点放入栈中一遍最初就弹出 stack.add(root); while (!stack.isEmpty()){ //取出栈顶结点,并将其暂时存入temp TreeNode temp = stack.pop(); System.out.println("当前结点数据: "+temp.getData()); //栈是后进先出结构,故先存入右子结点,再存入左子结点 if (temp.rightChild != null) stack.push(temp.getRightChild()); if (temp.leftChild != null) stack.push(temp.getLeftChild()); } } /** * 中序遍历法 * 递归版本 */ public void recurseInOrderTraverse(TreeNode root){ if (root == null) return; recurseInOrderTraverse(root.leftChild); System.out.println("当前结点数据: "+root.getData()); recurseInOrderTraverse(root.rightChild); } /** * 中序遍历法 * 非递归版本 */ public void inOrderTranverse(TreeNode root){ if (root == null) return; Stack<TreeNode> stack = new Stack<TreeNode>(); //依靠root!=null进入循环 while (!stack.isEmpty() || root != null){ //如果根结点存在就将根节点压栈 if (root != null){ stack.push(root); //更新根结点 root = root.leftChild; } else { //如果根结点不存在就弹栈,使用temp保存弹栈元素 TreeNode temp = stack.pop(); //打印弹栈元素 System.out.println("当前结点数据: "+temp.getData()); //更新根结点 root = temp.rightChild; } } } /** * 后序遍历法 * 递归版本 */ public void recursePostOrderTraverse(TreeNode root){ if (root == null) return; recursePostOrderTraverse(root.leftChild); recursePostOrderTraverse(root.rightChild); System.out.println("当前结点数据: "+root.getData()); } /** * 后序遍历法 * 递归版本 */ public void postOrderTraverse(TreeNode root){ if (root == null) return; Stack<TreeNode> stack = new Stack<TreeNode>(); stack.push(root); //初始化打印过的结点 TreeNode printedNode = null; while (!stack.isEmpty()){ //获取栈顶结点 root = stack.peek(); //如果一个结点的左子结点存在且该结点的左右子节点均未被打印,则说明这个结点是新的,将其压入栈 if (root.leftChild != null && printedNode != root.getLeftChild() && printedNode != root.getRightChild()){ stack.push(root.getLeftChild()); } //如果一个结点左子结点为空或者已被打印,而且该结点的右子结点存在且未被打印,则将其压入栈中 else if (root.rightChild != null && printedNode != root.getRightChild()){ stack.push(root.getRightChild()); } //若以上两个均不满足,说明该结点不能存在左右结点或者该结点的子结点均已被打印,则将该结点弹出并打印 else { System.out.println("当前结点数据: "+stack.pop().getData()); //更新已被打印过的结点 printedNode = root; } } }}
测试代码
package BinaryTree;/** * Created by jiangxs on 17-5-29. */public class BinaryTreeTest { public static void main(String[] args) { BinaryTree bt = new BinaryTree(); BinaryTree.TreeNode root = bt.creatBinTree(); System.out.println("----------递归前序遍历----------"); bt.recursePreOrderTraverse(root); System.out.println("----------非递归前序遍历--------"); bt.preOrderTraverse(root); System.out.println("----------递归中序遍历----------"); bt.recurseInOrderTraverse(root); System.out.println("----------非递归中序遍历--------"); bt.inOrderTranverse(root); System.out.println("----------递归后序遍历----------"); bt.recursePostOrderTraverse(root); System.out.println("----------非递归后序遍历--------"); bt.postOrderTraverse(root); }}
测试结果
----------递归前序遍历----------当前结点数据: A当前结点数据: B当前结点数据: D当前结点数据: E当前结点数据: C当前结点数据: F当前结点数据: G----------非递归前序遍历--------当前结点数据: A当前结点数据: B当前结点数据: D当前结点数据: E当前结点数据: C当前结点数据: F当前结点数据: G----------递归中序遍历----------当前结点数据: D当前结点数据: B当前结点数据: E当前结点数据: A当前结点数据: F当前结点数据: C当前结点数据: G----------非递归中序遍历--------当前结点数据: D当前结点数据: B当前结点数据: E当前结点数据: A当前结点数据: F当前结点数据: C当前结点数据: G----------递归后序遍历----------当前结点数据: D当前结点数据: E当前结点数据: B当前结点数据: F当前结点数据: G当前结点数据: C当前结点数据: A----------非递归后序遍历--------当前结点数据: D当前结点数据: E当前结点数据: B当前结点数据: F当前结点数据: G当前结点数据: C当前结点数据: AProcess finished with exit code 0
参考:《大话数据结构》
阅读全文
1 0
- 大话数据结构(七)——二叉树创建与遍历(递归、非递归)的java实现
- 【数据结构】二叉树的遍历(递归与非递归)
- 数据结构与算法学习记录--二叉树的创建,递归遍历,非递归遍历的实现
- Java实现二叉树的创建、递归/非递归遍历
- 【数据结构】Java实现二叉树遍历(非递归)
- 【数据结构与算法】二叉树的遍历(递归遍历、非递归遍历、层序遍历)
- Java实现二叉树的递归与非递归遍历
- C语言数据结构实现二叉树递归与非递归遍历(数据结构第四次实验)
- 数据结构——二叉树(递归与非递归遍历)
- 二叉树的遍历(递归与非递归)java实现
- JAVA实现二叉树的前、中、后序遍历(递归与非递归)
- 二叉树遍历的递归与非递归实现(java)
- 递归与非递归实现树的遍历(java)
- 二叉树遍历(递归与非递归实现)
- 二叉树的先序、中序、后序遍历方法(递归与非递归方法)——《数据结构》
- 数据结构——二叉树的递归与非递归遍历(先序,中序,后序)
- 二叉树的常用操作(创建、先中后序递归与非递归遍历、层序遍历)
- 二叉树的遍历(递归实现+非递归实现)
- CodeVS 1907 网络流最小割 解题报告
- Java IO学习笔记(五):内存操作流
- Lucene3.0 优化操作
- IBM的单点登录
- Java IO学习笔记(四):字节
- 大话数据结构(七)——二叉树创建与遍历(递归、非递归)的java实现
- 第1课
- (193)矢量操作
- 欢迎使用CSDN-markdown编辑器
- Java IO学习笔记(三):字节流与字符流
- Java IO学习笔记(二):RandomAccessFile类
- MySQL创建数据库和数据库表
- Java IO学习笔记(一):File类
- NIO缓冲区的基本概念