大话数据结构(七)——二叉树创建与遍历(递归、非递归)的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
原创粉丝点击