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

作为一名大三狗,真的是很惭愧。最近要面临面试了,才开始着急自己的数据结构,其实二大那会我很认真的学了,当时的那些什么哈夫曼树也都自己亲手写过,但是后面不练的话真的是手感都没有了,想当初自己算法也是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

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

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 220,295评论 6 512
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,928评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,682评论 0 357
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,209评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,237评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,965评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,586评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,487评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,016评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,136评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,271评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,948评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,619评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,139评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,252评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,598评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,267评论 2 358

推荐阅读更多精彩内容