二叉树的遍历和查找

就如图所示的二叉树进行遍历:

这里写图片描述

(1)前序遍历:A B D G H C E I F
(2)中序遍历:G D H B A E I C F
(3)后序遍历:G H D B I E F C A

递归前序遍历算法:

    private void preOrderTraverse(Node rootNode){
        if(null != rootNode){
            System.out.print(rootNode.data+" ");
            preOrderTraverse1(rootNode.leftNode);
            preOrderTraverse1(rootNode.rightNode);
        }
    }

递归中序遍历算法:

    private void inOrderTraverse(Node rootNode){  //线索二叉树的时候定义一个变量,
                                                //始终指向刚刚访问过的结点
        if(null != rootNode){
            inOrderTraverse1(rootNode.leftNode);
            System.out.print(rootNode.data + " ");
            inOrderTraverse1(rootNode.rightNode);
        }
    }

递归后序遍历算法:

    private void postOrderTraverse(Node rootNode){
        if(null != rootNode){
            postOrderTraverse1(rootNode.leftNode);
            postOrderTraverse1(rootNode.rightNode);
            System.out.print(rootNode.data + " ");
        }
    }

以上三种递归遍历算法比较容易理解,要求能快速编写出来

其他递归遍历算法

前序遍历除了用递归遍历外,可以用非递归遍历,在非递归遍历中有两种方式;一种是利用栈实现循环先序遍历二叉树,另一种是利用栈模拟递归过程实现循环中序遍历二叉树

(1)利用栈实现循环先序遍历二叉树

    /**
     * 先序遍历非递归
     * 利用栈实现循环先序遍历二叉树 
     * 这种实现类似于图的深度优先遍历(DFS) 
     * 维护一个栈,将根节点入栈,然后只要栈不为空,出栈并访问,接着依次将访问节点的右节点、左节点入栈。 
     * 这种方式应该是对先序遍历的一种特殊实现(看上去简单明了),但是不具备很好的扩展性,在中序和后序方式中不适用
     * @param root
     */
    private void preOrderTraverse_circul1(Node root){
        if(root == null){
            return;
        }
        MyLinkedStack<Node> myStack = new MyLinkedStack<Node>();
        myStack.push(root);
        while(!myStack.isEmpty()){  //当不为空的时候
            Node tmpNode = myStack.pop();
            System.out.print(tmpNode.data+" ");
            if(tmpNode.rightNode != null){
                myStack.push(tmpNode.rightNode);
            }
            if(tmpNode.leftNode != null){
                myStack.push(tmpNode.leftNode);
            }
        }
    }

学习这段代码要自己手执行一遍,才能理解

二、利用栈模拟递归过程实现循环中序遍历二叉树

    /**
     *      * @param root 树的根节点 
     * 利用栈模拟递归过程实现循环先序遍历二叉树 
     * 这种方式具备扩展性,它模拟递归的过程,
     * 将左子树点不断的压入栈,直到null,然后处理栈顶节点的右子树 
     * @param root
     */
    private void preOrderTraverse_stack1(Node root){
        if(root == null){
            return;
        }
        MyLinkedStack<Node> myStack = new MyLinkedStack<Node>();
        while(root != null || !myStack.isEmpty()){
            while(root != null){
                System.out.print(root.data+" ");            //先访问数据
                myStack.push(root);             //push进去是为了能pop出来右孩子
                root = root.leftNode;  //将左子树不断压入栈,直到null,然后处理栈顶结点的
                                    //右子树
            }
            root = myStack.pop();
            root = root.rightNode;                      
        }       
    }

中序遍历,利用栈模拟递归过程实现循环中序遍历二叉树
利用栈模拟递归过程实现循环中序遍历二叉树 :

    /**
     * @param root 树根节点 
     * 利用栈模拟递归过程实现循环中序遍历二叉树 
     * 思想和上面的preOrderTraverse_stack2相同,
     * 只是访问的时间是在左子树都处理完直到null的时候出栈并访问。
     */
    private void inOrderTraverse_stack1(Node root){
        if(null == root){
            return;
        }
        MyLinkedStack<Node> myStack = new MyLinkedStack<Node>();
        while(root != null || !myStack.isEmpty()){
            while(root != null){
                myStack.push(root);
                root = root.leftNode;
            }
            root = myStack.pop();
            System.out.print(root.data + " ");
            root = root.rightNode;
        }
    }

注意与“利用栈模拟递归过程实现循环中序遍历二叉树”的代码做比较

层序遍历的算法;层序遍历充分利用队列的先入先出特性
层序遍历算法:

    /**
     * 层序遍历,使用队列
     * @param root
     */
    private void levelTraverse1(Node root){
        if(null == root){
            return;
        }
        MyLinkedQueue<Node> myQueue = new MyLinkedQueue<Node>();
        myQueue.insert(root);
        while(!myQueue.isEmpty()){
            Node tmp = myQueue.delete();
            System.out.print(tmp.data+" ");
            if(tmp.leftNode != null) myQueue.insert(tmp.leftNode);
            if(tmp.rightNode != null) myQueue.insert(tmp.rightNode);
        }
    }

根据二叉树的结点的数据查找是否存在该节点

    private Node findNode1(Node node, String data){
//      System.out.println(node.data);
        if(null == node || null == data || "".equals(data)){
            return null;
        }else{
            if(node.data.equals(data)){
                return node;
            }               //递归出口
            //以下代码可以优化,这样写比较容易理解
            Node retNode1;Node retNode2;
            retNode1 = findNode1(node.leftNode, data);
            if(retNode1 != null){
                return retNode1;
            }

            retNode2 = findNode1(node.rightNode, data);
            if(retNode2 != null){
                return retNode2;
            }
        }

        return null;
    }

其实这段代码是根据先序递归遍历的顺序查找的

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值