美文网首页
数据结构——二叉树的创建和遍历

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

作者: 李die喋 | 来源:发表于2019-11-24 11:06 被阅读0次

作为一名大三狗,真的是很惭愧。最近要面临面试了,才开始着急自己的数据结构,其实二大那会我很认真的学了,当时的那些什么哈夫曼树也都自己亲手写过,但是后面不练的话真的是手感都没有了,想当初自己算法也是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<TreeNode> 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<total-1;i++){
            TreeNode node = list.poll();
            System.out.println("是否给当前节点创建左孩子(是输1 否输0):");
            int a = in.nextInt();
            if(a==1 && node.left == null){
                TreeNode leftNode = new TreeNode(arr[k++],null,null);
                node.left = leftNode;
                list.add(leftNode);
            }
            System.out.println("是否给当前节点创建右孩子(是输1 否输0):");
            int b = in.nextInt();
            if(b==1 && node.right == null){
                TreeNode rightNode = new TreeNode(arr[k++],null,null);
                node.right = rightNode;
                list.add(rightNode);
            }
        }
        return head;
    }

//创建结点 里面有些方法是没有用上的
class TreeNode{
    char ch;//数据
    TreeNode left = null;//左指针
    TreeNode right = null;//右指针

    public TreeNode(){

    }

    public TreeNode(char ch,TreeNode left,TreeNode right){
        this.ch = ch;
        this.left = left;
        this.right = right;
    }

    public void setValue(char value){
        this.ch = value;
    }

    public char getValue(){
        return ch;
    }
二叉树例子.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<TreeNode> 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<TreeNode> 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<TreeNode> 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

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

相关文章

  • 数据结构

    编写了数据结构的二叉树的创建和遍历程序

  • 二叉树的创建和遍历

    二叉树的创建和遍历 如图所示的二叉树,我们用C++来实现其创建和...

  • 二叉树的遍历

    数据结构算法 二叉树的遍历

  • python实现二叉树的遍历

    二叉树是一种非常重要的数据结构,很多其它数据结构都是基于二叉树的基础演变而来的。对于二叉树,有深度遍历和广度遍历,...

  • 算法系列--二叉树的三种遍历的六种实现

    0. 二叉树是常见的数据结构,二叉树常见的遍历方式有前序遍历,中序遍历和后序遍历。前序遍历就是中-左-右节点的顺序...

  • 二叉树的四种遍历方法

    二叉树的数据结构 1、前序遍历(递归) 2、中序遍历(递归) 3、后序遍历(递归) 4、层次遍历(队列)

  • Python实现深度优先与广度优先

    二叉树的两种遍历是数据结构的经典考察题目, 广度遍历考察队列结构, 深度遍历考察递归 二叉树 深度优先 先序遍历(...

  • 数据结构第12讲 二叉树的层次遍历

    数据结构第12讲 二叉树的层次遍历 二叉树的遍历一般有先序遍历、中序遍历和后序遍历,这三种遍历比较简单。今天我们讲...

  • 算法学习

    ### 实现二叉树以及二叉树遍历数据结构递归比较重要 1.先序遍历 先序遍历,就是先遍历根节点然后再遍历左子树,最...

  • 二叉树

    二叉树的创建和遍历都可以通过递归实现 三种遍历方式的记忆:前序遍历 根节点==》左节点==》右节点中序遍历 ...

网友评论

      本文标题:数据结构——二叉树的创建和遍历

      本文链接:https://www.haomeiwen.com/subject/tzqlwctx.html