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

    认识遍历

    含义:按某条路径巡访树中的每个结点,使得每个节点均被访问一次,且仅被访问一次

    目的:它是树结构增、删、改、查以及排序运算的前提,是二叉树一切运算的基础和核心。

    遍历规则

    二叉树由根、左子树、右子树构成,定义为D、L、R

    D、L、R的 组合定义了六种可能的遍历方案:

    LDR,LRD,DLR,DRL,RDL,RLD

    若限定先左后右,则有三种实现方案:

      DLR      LDR     LRD  
       先序遍历      中序遍历    后续遍历

    注:“先、中、后”的意思是指访问的结点D是先于子树出现还是后于子树出现。

    先序遍历

    先序遍历序列:A B D C

    任意一个结点均处在其子女结点的前面(根结点在前)

    中序遍历

    中序遍历序列:B D A C

    根结点左右分别为左右子树的所有结点。

     后序遍历

    后序遍历序列:D B C A

    遍历递归算法

    结点数据类型自定义

    typedef struct node{

    int data;

    struct node *lchild,*rchild;

    }node;

    node *root;

    先序遍历算法

    status PreOrderTraversal(BiTree T)

    {if (T)  //非空二叉树

    {visit(T->data);  //访问D

    PreOrderTraversal(T->lchild);  //递归遍历左子树

    PreOrderTraversal(T->rchild);  //递归遍历右子树

    }

    return OK;  }

    中序遍历算法

    status InOrderTraversal(BiTree T)

    {if (T)  //非空二叉树

    {

    InOrderTraversal(T->lchild);  //递归遍历左子树

    visit(T->data);  //访问D

    InOrderTraversal(T->rchild);  //递归遍历右子树

    }

    return OK;  }

    后序遍历算法

    status PostOrderTraversal(BiTree T)

    {if (T)  //非空二叉树

    {

    PostOrderTraversal(T->lchild);  //递归遍历左子树

    PostOrderTraversal(T->rchild);  //递归遍历右子树

    visit(T->data);  //访问D

    }

    return OK;  }

    遍历的分析

    从前面的三种遍历算法可以知道:如果将visit语句抹去,从递归的角度看,这三种算法是完全相同的,或者说这三种遍历算法的访问路径是相同的,只是访问结点的时机不同。

     从虚线的出发点到终点的路径上,每个结点经过3次。

    第1次经过时访问,是先序遍历。

    第2次经过时访问,是中序遍历。

    第3次经过时访问,是后序遍历。

    二叉树遍历的时间效率和空间效率

    时间效率:O(n)//每个结点只访问一次

    空间效率:O(n) //栈占用的最大辅助空间

    非递归算法(中序)

    遇到结点就把它入栈,然后遍历它的左子树。

    当左子树遍历结束,从栈顶弹出该结点并访问它。

    以右指针再去中序遍历右子树。

    Status InOrderTraverse(BiTree T,Status(*Visit)(TElemType e)){

    InitStack(S); p=T;

    while (p || !StackEmpt(s)){

    if(p) {Push(S,p); p=p->lchild;}  //根指针进栈,遍历左子树         //调换位置,可以更改为先序遍历

    else{

    Pop(S,p);

    if(! Visit(p->data)) return ERROR;

    p=p->rchild;                      //调换位置,可以更改为先序遍历

    }//else

    }//while

    return OK;

    }

    二叉树的遍历

    二叉树的遍历就是按某条路径巡访树中每个结点,使得每个节点均被访问一次,且仅被访问一次。

    层序遍历

    从上之下,从左到右,顺序访问

    队列数据结构:先进先出   根-左-右

    队列实现:

    1、根结点入队;

    2、执行下列循环:结点出队,访问该结点,其左、右儿子入队;

    3、队列为空时,结束。

    层序遍历的算法过程为:

    1、根结点入队;

    2、从队列中取出一个元素,即访问该元素;

    3、若该元素结点的左、右孩子非空,则将其左、右孩子结点元素顺序入队;

    4、循环执行2,3步,直到队列为空,结束。

    void LevelOrderTraversal(BinTreeBT){

    Queue Q; BinTree T;

    if(!BT) return;  //若是空树则直接返回

    Q = CreatQueue(MaxSize); //创建并初始化队列

    AddQ(Q,BT);

    T = DeleteQ(Q);

    printf(“%d ”,T->Data);  //访问取出队列的结点

    if (T->Left)AddQ(Q,T->left);

    if(T->Right)AddQ(Q,T->Right);

    }

    统计二叉树中叶子结点的个数(先序遍历)

    算法思想:

    利用先序(或中序或后序)遍历二叉树,在遍历过程中查找叶子结点,并进行计数。

    在遍历算法中增加一个“计数”的参数;

    将遍历算法中“访问结点的操作”改为:若是叶子结点,则计数器加1.

    status PreOrderTraversal(BiTree T)

    {if (T)  //非空二叉树

    {if(!T->lchild)&&(!T->rchild)

    count++;   //对叶子结点计数  printf(‘’%d‘’,T->data)

    PreOrderTraversal(T->lchild);  //递归遍历左子树

    PreOrderTraversal(T->rchild);  //递归遍历右子树

    }

    return OK;  }

    求二叉树的深度

    算法思想:

    首先,分析二叉树的深度和它的左、右子树深度之间的关系

    二叉树的深度应该为其左、右子树深度的最大值加1.

    由此,可以先分别求得左、右子树的深度。

    后序遍历

    int PostOrderTraversal(BiTree BT)

    { int HL ,HR,MaxH;

    if (BT)  //非空二叉树{

    HL=PostOrderGetHeight(BT->left);  //左子树深度

    HR=PostOrderGetHeight(BT->right);  //右子树深度

    MaxH=(HL >HR) ? HL:HR;  //取左右子树较大的深度

    return (MaxH +1)  //返回树的深度

    }

    else return 0;  //空树返回0  

    }

     由两种遍历序列确定二叉树

    已知三种遍历中的任意两种序列,能否唯一确定一棵二叉树呢?

    答案是:必须要有中序遍历才行!

    没有中序的困扰:

    先序遍历序列:AB

    后序遍历序列:BA

        A         A

       ↙          ↘

     B               B

     不能确定左右子树的边界

     由二叉树的先序和中序来确定二叉树

    由先序遍历序列,确定第一个结点元素为根结点;

    根据根结点在中序序列中的位置,分割出左右子树的子序列;

    对左子树和右子树再分别递归使用相同的方法继续分析。

    先序序列:根  左子树  右子树

    中序序列:左子树     根  右子树

     例:

    先序序列:a  bcde  fghij

    中序序列:cbed  a  ghijf

  • 相关阅读:
    Edge浏览器主页被360劫持怎么办 ?
    wpf小技巧——datagrid 不出现 滚动条问题
    c++学习资料
    Mosquitto创建MQTT服务器提示Starting in local only mode的解决办法
    【转】在 Golang 中使用 Cobra 创建 CLI 应用
    【转】Golang的HTTP操作大全
    BigDecimal类中的3个toString方法
    Path is not a working copy directory
    Cannot deserialize instance of `java.lang.String` out of START_OBJECT token
    sqlserver判断字符串是否是纯数字
  • 原文地址:https://www.cnblogs.com/privilege/p/11218220.html
Copyright © 2011-2022 走看看