博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
创建二叉树、递归/非递归 先序/中序/后序遍历二叉树算法
阅读量:4059 次
发布时间:2019-05-25

本文共 5122 字,大约阅读时间需要 17 分钟。

package BinaryTree;import java.util.Scanner;import java.util.Stack;//二叉树的节点public class Node {    String value;    Node left;    Node right;    public Node(String value){        this.value = value;    }    /**     * 创建一个二叉树     * 规定:不允许输入空数据,即输入的二叉树得至少有一个节点     * para:data是一个字符串数组,存储二叉树先序遍历得到的节点值,     * start是节点值在数组中开始下标,end是节点值在数组中的结束下标,如果数组中没有值,start = -1, end = -1     * 在进行判断时,不能使用data.length进行判断,因为递归函数使用的是同一个字符串数组作为输入变量,只是start和end的值不一样     * 输入的形式是作为一个满二叉树进行输入,空节点用$号代替     * 采用先序的方式创建一个二叉树     */    public static Node createBinaryTree(String[] data,int start,int end){//由于使用递归算法,所有得多设置几个参数        if((end == start)){//只有一个节点的情况下,这就是递归结束条件,不可能出现end小于start的情况            if(data[start].equals("$")){                return null;            }else{                return new Node(data[start]);            }        }else{            if(data[start].equals("$")){//如果说某个子树的根节点为$,直接返回null,下面也不用计算了1,                return null;            }            Node root = new Node(data[start]);            int halfLength = (end - start)/2;            Node leftChild = createBinaryTree(data,start+1,start+halfLength);            Node rightChild = createBinaryTree(data,start+halfLength+1,start+2*halfLength);            root.left = leftChild;            root.right = rightChild;            return root;        }    }    /**     * 先序递归输出二叉树     */    public static void preOrder(Node root){        if(root != null){            System.out.print(root.value+" ");            preOrder(root.left);            preOrder(root.right);        }    }    /**     * 中序递归输出二叉树     */    public static void inOrder(Node root){        if(root != null){            inOrder(root.left);            System.out.print(root.value+" ");            inOrder(root.right);        }    }    /**     * 后序递归遍历二叉树     */    public static void postOrder(Node root){        if(root != null){            postOrder(root.left);            postOrder(root.right);            System.out.print(root.value+" ");        }    }    /**     * 后序非递归遍历二叉树     * 后序非递归得使用到栈的结构     * 两层循环     * 我们要记得的是非递归遍历的栈中保存的是一个路径上的节点     * 出栈时访问,在栈中就没有访问     * 如果是回退到一个节点,那么只有可能该节点右子树和该节点没有被访问,该节点的左子树肯定被访问了     * 总结一下:外循环栈不为空,内循环一个左分支持续入栈,右分支持续出栈,出栈判断栈是否为空     */    public static void postOrderNotRecursive(Node root){        Stack
stack = new Stack<>();//<>是泛型机制 if(root == null){ return; } Node node = root; stack.push(node); node = node.left; //两层循环、最外层循环就是栈不为空,因为根节点是第一个进栈,最后一个出栈的,但是得先进栈根节点 while(!stack.isEmpty()){ while(node != null){ stack.push(node); node = node.left; } //到这儿是左遍历结束,现在的目的是访问栈顶节点的右子树,先把这个节点拿出来,不能pull出来 //当这个时候,弹出栈中的右分支,直到遇到左节点,这里稍微难写一点,注意,右分支不是右子树为空的节点,而是栈上节点是栈下节点的右子节点 //上一次弹出的节点如果是栈顶节点的右节点,则弹出栈顶节点 Node rightNode = null; node = stack.peek(); while(node.right == rightNode){ rightNode = stack.pop(); System.out.print(rightNode.value+" "); if(!stack.isEmpty()) { node = stack.peek(); }else{ return; } } node = node.right; } } /** * 先序遍历非递归形式 * 也要使用栈 */ //仍然使用栈结构 //循环条件是什么呢? //因为栈中元素是没访问过的,而根节点是第一个访问的。 //之前想过,只有后序遍历栈中的元素有规律,而先序和中序都没有什么规律。 //其实先序遍历的非递归形式很简单,我们要记住:一个节点访问过了就一定出栈了,如果在栈中,就一定是没有访问过的。 //那么就很简单了,根节点,压入,弹出,但是弹出之前得先把它的左右节点压入栈中,不然的话,左右子树的信息会全部丢失,那么又有问题来了 //先压入哪个节点呢?因为栈是先进后出,也就是先压入的后访问,那么我们自然得先把右节点压进去了,如果有子节点不为空,那就不用压入了, //因为节点的访问是从栈中取出再访问,节点的压入,也是把一个节点弹出,然后拿它的左右子节点压入,那如果栈中没元素了,就没元素访问,也没元素压入了 //所有循环条件也是栈不为空 public static void preOrderNotRecursive(Node root){ if(root == null){ return; } Stack
stack = new Stack<>(); Node node = root; stack.push(node); while(!stack.isEmpty()) { node = stack.pop(); System.out.print(node.value+" "); if (node.right != null) {//先压入右节点,再压入左节点 stack.push(node.right); } if (node.left != null) { stack.push(node.left); } } } /** * 中序遍历的非递归形式 * 中序的外层循环结束条件变了,不是栈不为空了,而是弹出节点的右节点不为空, */ public static void inOrderNotRecursive(Node root){ if(root == null){ return; } Stack
stack = new Stack<>(); Node node = root; while(node !=null) { while (node != null) { stack.push(node); node = node.left; } do { node = stack.pop(); System.out.print(node.value + " "); node = node.right; } while(!stack.isEmpty()&&node == null);//和非递归后续遍历一样,在进行持续出栈的时候一定要判断栈不为空。 } } /** * 测试函数 */ public static void main(String[] args){ Scanner sc = new Scanner(System.in); String s = sc.nextLine(); String[] data = s.split(","); Node root = createBinaryTree(data,0,data.length-1); inOrderNotRecursive(root); }}

算法时间复杂度是O(N),空间复杂度是O(h),h是树的高度。

转载地址:http://iizji.baihongyu.com/

你可能感兴趣的文章
【数据结构周周练】004顺序栈与链栈 -数制转换
查看>>
C++函数返回值介绍(含return 0 与 return 1 与 return -1介绍)
查看>>
C++报错:读取位置 0xFFFFFFFFFFFFFFFF 时发生访问冲突
查看>>
【数据结构周周练】005顺序队列与链队 -扑克牌的筛选
查看>>
【数据结构周周练】006队列基本操作-顺序结构及链式结构实现
查看>>
C++类、结构体、函数、变量等命名规则详解
查看>>
【数据结构周周练】007顺序结构实现完全二叉树操作- 求编号i与j最近公共祖先结点
查看>>
C++ goto语句详解
查看>>
【数据结构周周练】008 二叉树的链式创建及测试
查看>>
【数据结构周周练】009 二叉树的先序、中序、后序遍历(递归算法实现)
查看>>
【数据结构必备基本知识】递归与迭代的联系、区别与优缺点对比详解
查看>>
【数据结构周周练】010 递归算法实现二叉树的创建与遍历
查看>>
【数据结构周周练】011 非递归算法实现二叉树的遍历
查看>>
【数据结构周周练】012 利用队列和非递归算法实现二叉树的层次遍历
查看>>
【数据结构周周练】013 利用栈和非递归算法求二叉树的高
查看>>
【数据结构周周练】014 利用栈和非递归算法求链式存储的二叉树是否为完全二叉树
查看>>
【数据结构周周练】015 利用递归算法创建链式存储的二叉树并转换左右孩子结点
查看>>
【数据结构周周练】016 利用递归算法及孩子兄弟表示法创建树、遍历树并求树的深度
查看>>
【数据结构周周练】017 利用递归算法及孩子兄弟表示法创建森林、遍历森林并求森林的叶子结点个数
查看>>
【数据结构必备基本知识】数据结构常用预定义常量、类型及头文件
查看>>