2叉数的遍历

该文主要介绍2叉数的基本遍历的实现,在此之前,首先应该知道2叉数有哪些遍历?

154433_pyn0_1452675.png

先序遍历:根-->左-->右    即先访问根结点,然后访问左子树,最后访问右子树。在遍历左、右子树时,仍然如此。

上图遍历结果:A,B,D,E,C,F,G。

中序遍历:左-->根-->右    即先访问左子树,然后访问根结点,最后访问右子树。在遍历左、右子树时,仍然如此。

上图遍历结果:D,B,E,A,F,C,G。

后序遍历:左-->右-->根    即先访问左子树,然后访问右子树,最后访问根结点。在遍历左、右子树时,仍然如此。

上图遍历结果:D,E,B,F,G,C,A。

层次遍历:1层,2层,3层,依次访问下来,如果某一层元素超过两个,那么从先左后右访问。

上图遍历结果:A,B,C,D,E,F,G。(这个已经简单不行了)

深度遍历:首先访问根结点(A),然后沿着它的左结点依次访问(B,D),至到访问到最后一层(也就是D),再返回到它的父亲(B),访问他的右结点(E)。然后这样重复地访问完所有结点。

上图遍历结果:A,B,D,E,C,F,G。

备注:

    1.上面的先、中、后序遍历,主要看的就是根在访问顺序中所在的位置。“根左右”,根在前,所以叫先序遍历。“左根右”,根在中,所以叫中序遍历。

    2.在中序遍历中,有一种很快得出其遍历的结果的方法。叫做投影法。(你以为我会把这个方法的链接放在这里么?No,我只会告诉你,请百度百科“中序遍历”,这里有我想给你看的“投影法”。)

如何实现

    先序遍历:首先访问根,然后递归访问左子树,再递归访问右子树即可。

    中/后序遍历:类似于先序遍历。等下看源码就明白了。

层次遍历

    首先将根入队列(先进先出),然后就循环判断这个队列是否为空。只要队列不为空,就取出队列中的一个结点,访问这个结点的值,再将这个结点的左结点入队列,再将这个队列的右结点入队列。

层次遍历详细解释

    以上图的2叉数为例,首先将根A结点入队列,现在用while来循环判断队列是否为空。很明显,不为空。所以取出队列中的结点(A)来访问,然后,这个结点(A)的左结点(B)不为空,入队列,这个结点的右结点(C)也不为空,入队列。所以现在队列中就又有了B、C两个结点,所以循环继续。拿出B,访问B,再将B的左右结点D、E入队列。现在队列中就有了C、D、E了。队列不为空,所以循环继续,拿出C,访问C,再将F,G入队列。现在队列中就是D、E、F、G了。队列不为空,拿出D访问,D没有子结点,那么没有新的结点入队列,但队列还没有为空,所以接着拿出E来访问,E也没有子结点,所以也没有新的结点入队列,但队列还没有为空,接着再拿队列中的F来访问,依次类推了。(写得很罗嗦,希望能把这个过程解释清楚。)

深度遍历

     首先将根入栈(先进后出),然后就循环判断这个栈是否为空。只要栈不为空,就取出栈中的一个结点,访问这个结点的值,再将这个结点的右结点入栈,再将这个结点的左结点入栈。(很类似于层次遍历的实现,只是所用的数据结构由队列变成了栈,入队列是先左后右,入栈的顺序是先右后左)

深度遍历详细解释

    这个很类似于层次遍历的详细解释,我简单得说一下。首先根A入栈,然后循环判断栈是否为空,现在栈里有结点A,所以不为空,所以取出A,访问A,将C、B入栈(也就是将A的右结点入栈,然后左结点入栈,和层次遍历时是相反的)。再判断栈是否为空,现在栈中有C、B。由于栈是后进先出的结构,所以这里是B弹出栈,访问B,再将B的子结点E、D入栈,那现栈中就有了C、E、D。判断栈不空,又弹出D,访问D,将D的子结点入栈。这样类推下去,就完成了遍历。

java代码如下:(有点多,不过该代码可测试运行)

package com.cdu.binaryTree;

import java.util.LinkedList;

public class MyBinaryTree {
    public static void main(String[] args) {
        //初始化一棵2叉数
        BinaryTree binaryTree = BinaryTree.initBinaryTree();

        // 先序遍历
        System.out.println("先序遍历:");
        binaryTree.preOrderTraversal(binaryTree);
        System.out.println("\n");
        
        // 中序遍历
        System.out.println("中序遍历:");
        binaryTree.midOrderTrversal(binaryTree);
        System.out.println("\n");
        
        // 后序遍历
        System.out.println("后序遍历:");
        binaryTree.postOrderTrversal(binaryTree);
        System.out.println("\n");
        
        // 层次遍历
        System.out.println("层次遍历:");
        binaryTree.levelTraversal(binaryTree);
        System.out.println("\n");
        
        // 深度遍历
        System.out.println("深度遍历:");
        binaryTree.depthTraversal(binaryTree);
        System.out.println("\n");
    }
}

class BinaryTree{
    private int data;                    //结点值 
    private BinaryTree left;             //左子结点
    private BinaryTree right;            //右子结点
    
    public BinaryTree(int data){
        this.data = data;
    }
    
    /**
     * @Description 初始化二叉数
     * @param 
     * @return 得到如下所示的二叉数
     *                             1
     *                          *      *
     *                     2                3
     *                  *   *               *   *    
     *                 4       5          6        7
     *                  *     * *
     *                   9   10 11
     *                       *    
     *                      8
     * 
     * 先序遍历结果:1,2,4,9,5,10,8,11,3,6,7
     * 中序遍历结果:4,9,2,8,10,5,11,1,6,3,7
     * 后序遍历结果:9,4,8,10,11,5,2,6,7,3,1
     * 层次遍历结果:1,2,3,4,5,6,7,9,10,11,8
     * 深度遍历结果:1,2,4,9,5,10,8,11,3,6,7
     */
    public static BinaryTree initBinaryTree(){
        BinaryTree root = new BinaryTree(1);
        BinaryTree node2 = new BinaryTree(2);
        BinaryTree node3 = new BinaryTree(3);
        BinaryTree node4 = new BinaryTree(4);
        BinaryTree node5 = new BinaryTree(5);
        BinaryTree node6 = new BinaryTree(6);
        BinaryTree node7 = new BinaryTree(7);
        BinaryTree node8 = new BinaryTree(8);
        BinaryTree node9 = new BinaryTree(9);
        BinaryTree node10 = new BinaryTree(10);
        BinaryTree node11 = new BinaryTree(11);
        
        root.setLeft(node2);
        root.setRight(node3);
        
        node2.setLeft(node4);
        node2.setRight(node5);
        
        node3.setLeft(node6);
        node3.setRight(node7);
        
        node4.setRight(node9);
        
        node5.setLeft(node10);
        node5.setRight(node11);
        
        node10.setLeft(node8);
        
        return root;
    }
    
    /**
     * @Description 先序遍历
     * @param binaryTree 二叉数
     * @return
     */
    public void preOrderTraversal(BinaryTree binaryTree){
        // 当2叉数为空时,递归结束。
        if (binaryTree == null){
            return ;
        }else{
            System.out.print(binaryTree.getData() + ",");            //访问结点
            preOrderTraversal(binaryTree.getLeft());                 //递归遍历左子树
            preOrderTraversal(binaryTree.getRight());                //递归遍历右子树
        }
    }
    
    /**
     * @Description 中序遍历
     * @param binaryTree 二叉数
     * @return
     */
    public void midOrderTrversal(BinaryTree binaryTree){
        if (binaryTree == null){
            return ;
        }else{
            midOrderTrversal(binaryTree.getLeft());
            System.out.print(binaryTree.getData() + ",");
            midOrderTrversal(binaryTree.getRight());
        }
    }
    
    /**
     * @Description 后序遍历
     * @param binaryTree 二叉数
     * @return
     */
    public void postOrderTrversal(BinaryTree binaryTree){
        if (binaryTree == null){
            return ;
        }else{
            postOrderTrversal(binaryTree.getLeft());
            postOrderTrversal(binaryTree.getRight());
            System.out.print(binaryTree.getData()+ ",");
        }
    }
    
    /**
     * @Description 层次遍历:先将根节点入队列,然后判断只要队列不为空,
     *         那么就从队列中poll一个结点来访问,然后再将该结点的左结点入队列,然后再将右结点入队列
     * @param 
     * @return
     */
    public void levelTraversal(BinaryTree binaryTree){
        LinkedList<BinaryTree> queue = new LinkedList<BinaryTree>();
        if (binaryTree != null){
            queue.offer(binaryTree);
        }
        
        // 只要队列不为空,则遍历队列中结点
        while (!queue.isEmpty()){
            BinaryTree node = queue.poll();
            System.out.print(node.getData() + ",");
            
            // 若结点有子结点,那么将该结点的左、右结点存入队列
            if (node.getLeft() != null){
                queue.offer(node.getLeft());
            }
            if (node.getRight() != null){
                queue.offer(node.getRight());
            }
        }
    }
    
    /**
     * @Description 深度遍历:先将根节点入队列,然后判断只要栈不为空,
     *         那么就在栈中pop一个结点来访问,然后再将该结点的右结点压栈,然后再将左结点压栈
     * @param 
     * @return
     */
    public void depthTraversal(BinaryTree binaryTree){
        LinkedList<BinaryTree> stack = new LinkedList<BinaryTree>();
        if (binaryTree != null){
            stack.push(binaryTree);
        }
        
        // 只要栈不为空,则遍历栈中结点
        while(!stack.isEmpty()){
            BinaryTree node = stack.pop();
            System.out.print(node.getData() + ",");
            
            // 若结点有子结点,那么将该结点的右、左结点存入队列
            if (node.getRight() != null){
                stack.push(node.getRight());
            }
            if (node.getLeft() != null){
                stack.push(node.getLeft());
            }
        }
    }
    
    /*--------------getter and setter--------------------*/
    
    public int getData() {
        return data;
    }
    public void setData(int data) {
        this.data = data;
    }
    public BinaryTree getLeft() {
        return left;
    }
    public void setLeft(BinaryTree left) {
        this.left = left;
    }
    public BinaryTree getRight() {
        return right;
    }
    public void setRight(BinaryTree right) {
        this.right = right;
    }
}


    



转载于:https://my.oschina.net/u/1452675/blog/203361

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值