zoukankan      html  css  js  c++  java
  • 二叉树的递归遍历

    hello,大家好,明天就是"double eleven了,不知道大家准备好没有,我们还是加班加点的把二叉树来看一下。

    在讲遍历之前,我们首先应该了解一下二叉树是怎么建立的   

        3
       / 
      9  20
        /  
       15   7

    你可能会看到这样的一颗二叉树,那么这颗二叉树的根节点就是 3 ,而它的两个孩子结点就是 9 和 20 ,在我们建立一颗二叉树的时候,
    就算它只有一个或者没有孩子,我们也要把另外一个或两个孩子补上去,可以是空格,也可以是其他你自己定义的特殊字符。(但是补了字符的两个孩子就不用管了。)

    看了上面,相信你对二叉树已经有了一个印象了,让我们开始吧。

    一、结构体

    typedef struct node{
      elemtype data;                                    //注意这里的 elemtype 前面要设置成 char 类型(也就是字符串),

                                                                       //因为我们的二叉树可能会是字母什么的
      struct node*lchild,*rchild;                    //然后构造它的两个孩子指针,跟之前的 next 差不多,就是一个

                                                                       //指向左边的 next 和一个指向右边的 next
    }node,*btnode;                                           //常规定义 node 数组名和 btnode 指针类型名

     二、建立二叉树

        3
       / 
      9  20
        /  
       15   7

    关于方法,上面有提到,这里再提两点:

    1,在构造数的过程中,因为用到的是递归,所以当我们构造了 3 之后,再构造 9 时,就又可以把它看成是一个新的跟结点,这就是我们递归的原理。

    2,就是我们的二叉树的输入问题了,因为存在着某些孩子结点不存在的情况,所以在输入的时候就要注意了,如上图,我们的输入就应该是:

    (我们的表空字符设为 * )

      39**2015**7***

    是的,元素之间没有空格,我们的输入按照的是前序遍历的输入(当初满二叉树的前序),在没有的地方补上表空字符 * 就好了

    大家会不会问为什么 15 后面有两个 * 呢,我们前面提到的就算没有但是也要补上去就是这个了,9 后面构造了两个,然后构造的节点后面就不用管啦

    #注意最后一个节点必须多输入一个 *   ,这样计算机才知道已经输入完了

    Status creat_btree(btnode *T){
      elemtype ch;                                                                      //定义一下我们即将输入的元素
      scanf("%c",&ch);                                                                //直接一次性输入所有元素,计算机会一个

                                                                                                      //一个读取
      if(ch == ' ')   (*T) = NULL;                                                   //这里的空格就是我们的表空字符,当这个

                                                                                                      //孩子不存在的时候,就可以把它的指针

                                                                                                      //定位 NULL 了

        else{

        if(!((*T) = (btnode)malloc(sizeof(node)))) exit(ERROR);
        (*T)->data=ch;                                                            //空间分配成功,就可以给我们的结点赋值了。
        creat_btree(&(*T)->lchild);                                          //赋完值之后,利用递归,就可以先构造它的

                                                                                                      //左边(左子树)
        creat_btree(&(*T)->rchild);                                          //构造右子树

      }
      return OK;                                                                          //大家可以试着想一下,先是跟结点,然后是它

                                                                                                      //的孩子,当其中一个孩子的孩子的孩子......就算

                                                                                                      //没有的也构造完了,这个孩子就完成了,就

                                                                                                      //通过return 返回,

                                                                                                      //进行下一个递归,最后一个 return(也就是我们

                                                                                                      //多写的那个 * )

                                                                                                      //返回之后,就代表结束啦。
    }

    在遍历之前,我需要先设置一个 printf 函数

    Status print(elemtype e){
      printf("%c ",e);
      return OK;
    }

    三、前序遍历

    前序遍历首先访问根节点,然后遍历左子树,最后遍历右子树。(如下图)

    Status preorder(btnode T,Status (* print)(elemtype e)){                    //大家是不是对这里的参数感到奇怪,

                                                                                                              //通过后面的参数。我们就可以在子函数

                                                                                                              //里面调用我们定义了的其他子函数了
      if(T){                                                                                           //先判断根节点是否为空
        if (print(T->data))                                                                 //非空的话就可以输出它所代表的元素了
          if(preorder(T->lchild,print))                                           //然后再对左边进行遍历,注意一下 preorder 

                                                                                                              //的函数调用方式
            if(preorder(T->rchild,print))                                   //接着是右边
              return OK;                                                     //这个 OK 跟我们创建二叉树的原理是一样的

                                                                                                              //(其实递归的原理都差不多)
        else return ERROR;
      }
      else return OK;
    }

     四、中序遍历

    中序遍历是先遍历左子树,然后访问根节点,然后遍历右子树。

    Status inorder(btnode T,Status (* print)(elemtype e)){
      if(T){
        if(inorder(T->lchild,print))
          if (print(T->data))
            if(inorder(T->rchild,print))
              return OK;
          else return ERROR;                                              //别的就不多说了,提一下这里

                                                                                                        //的 return ERROR ,这个必须是跟

                                                                                                        //print(T->data)的 if 对齐的,为了防止

                                                                                                        //输入或者输出的时候有误,

                                                                                                        //用来退出错误项的。
      }
      else return OK;
    }

    五、后序遍历

    后序遍历是先遍历左子树,然后遍历右子树,最后访问树的根节点。

    Status postorder(btnode T,Status (* print)(elemtype e)){
      if(T){
        if(postorder(T->lchild,print))
          if(postorder(T->rchild,print))
            if (print(T->data))
              return OK;}
            else return ERROR;
      else return OK;
    }

    差不多就不多说了。

    附:main函数

    void main()
    {
      node t;btnode T = &t;                                            //这里记住要指一下。
      creat_btree(&T);
      printf("前序遍历为:");preorder(T,print); 
      printf(" 中序遍历为:");inorder(T,print);
      printf(" 后序遍历为:");postorder(T,print);
      system("pause");
    }

    所有图片来自LeetCode

  • 相关阅读:
    PHP 基础复习 2018-06-21
    PHP 基础复习 2018-06-17
    php 基础复习 2018-06-20
    [Android] ImageView.ScaleType设置图解
    Android中滑屏实现----触摸滑屏以及Scroller类详解 .
    Android Scroller简单用法 --View滚动
    Android下如何理解onMeasure,onLayout的过程
    ( 转)从四分钟到两秒——谈谈客户端性能优化的一些最佳实践
    8种形式的Android Dialog使用举例
    Android加载图片导致内存溢出(Out of Memory异常)
  • 原文地址:https://www.cnblogs.com/tqdlb/p/11830508.html
Copyright © 2011-2022 走看看