数据结构——二叉树的创建和遍历

作为一名大三狗,真的是很惭愧。最近要面临面试了,才开始着急自己的数据结构,其实二大那会我很认真的学了,当时的那些什么哈夫曼树也都自己亲手写过,但是后面不练的话真的是手感都没有了,想当初自己算法也是91分过的,但是就是练的太少以至于看一道题做好久,调试好几遍才出来。。。昨天在复习android的时候好累,就想着把自己建立的falg——写一遍树的创建和遍历,提上日程。写的过程中也是想着写着,终于还算是不错,就是树的后序非递归遍历那一块整了我好久,看了个电影回来调到晚上,再到今天早上,也是发现问题了最后写了出来。下面就总结一下吧。。。

树的创建

public TreeNode createTree(int total) {
        char[] arr = {'A','B','C','D','E','F','G','H'};
        int k=0;
        Scanner in = new Scanner(System.in);
        LinkedList list = new LinkedList<>();
        TreeNode left = null;
        TreeNode right = null;
        TreeNode head = new TreeNode(arr[k++],left,right);
        list.add(head);
        for(int i=1;i
二叉树例子.png

我画的图很丑,每次写题喜欢找一个例子放在脑子里去想。

树的递归遍历

递归遍历是比较简单的,但是我每次写题的时候不喜欢用递归,一个是递归耗时,另一个原因是我想不明白,虽然有关递归的问题问过别人很多次,也每次尝试用递归去想,但给我的感觉是递归总是很抽象,虽然有时候它的代码简单。在微机原理课接触到了中断服务程序,我突然对递归的理解又进了一步。递归的过程是不断压栈和弹栈的过程,在这个过程中还需要堆栈段对数据(cs:ip)进行保护,所以嘛,现在也不是很害怕有关递归的东西了。

    //递归 先序遍历 根左右
    public void preOrding(TreeNode root){
        if (root!=null){
            visit(root);
            preOrding(root.left);
            preOrding(root.right);
        }
    }

    //中序遍历 左中右
    public void inOrding(TreeNode root){
        if(root!=null){
            inOrding(root.left);
            visit(root);
            inOrding(root.right);
        }
    }

    //后序遍历 左右中
    public void postOrder(TreeNode root){
        if(root!=null){
            postOrder(root.left);
            postOrder(root.right);
            visit(root);
        }
    }

树的非递归遍历

    //非递归前序遍历 根左右
    public void preOrder(TreeNode root){
        Stack stack = new Stack<>();
        //stack.push(root);
        //System.out.print(root.ch);
        TreeNode p = root;
        while (p!= null || isEmpty(stack)){
           while (p!=null){
               System.out.print(p.ch);
               stack.push(p);
               p=p.left;
           }
           if(stack.isEmpty()){
               break;
           }else {
               p=stack.pop();
               p=p.right;
           }
        }
    }

    //非递归中序遍历
    public void inOrder(TreeNode root){
        TreeNode p = root;
        Stack stack = new Stack<>();
        while (p!=null || isEmpty(stack)){
            while (p!=null){
                stack.push(p);
                p=p.left;
            }
            if(isEmpty(stack)){
                p=stack.pop();
                System.out.print(p.ch);
                p=p.right;
            }
        }
    }

    //非递归后序遍历
    public void postOrder(TreeNode root){
        TreeNode p = root;
        TreeNode q = null;//判断当前节点是否作为右孩子访问过
        Stack stack = new Stack<>();
        while (p!=null || isEmpty(stack)){
            while (p!=null){
                stack.push(p);
                p=p.left;
            }
            if(isEmpty(stack)){
               p=stack.peek();
               if(p.right==null || p.right==q){
                   p=stack.pop();
                   System.out.print(p.ch);
                   q=p;
                   p=null;
               }else {
                   p=p.right;
               }
            }
        }
    }

我觉着非递归遍历里面要费一点时间的就是后序遍历了,主要是因为要考虑怎么去判断当前节点的右孩子没有被访问过。解决办法就是找一个指针q,用来记录访问过的节点,当再次访问的时候用p.right==q来比较,相同的话就直接打印p节点就好了。下面是我画的一张图:


后续非递归遍历——p和q的关系.png

算法还是要多练,多去想,有的时候是要会总结的,但是基础是必须的,加油哇!!!别去看别人怎么怎么样了。

你可能感兴趣的:(数据结构——二叉树的创建和遍历)