二叉树的三种非递归遍历

来源:互联网 发布:新装系统无法连接网络 编辑:程序博客网 时间:2024/06/05 23:53

后序遍历

  • 后序遍历
    这是最难操作的一部分。后序遍历先遍历左孩子,在遍历右孩子,最后遍历根节点。所以当一个节点返回的时候,必须知道这个节点是左孩子返回,还是右孩子返回。所以将节点和返回信息的标志放在一个结构体中,一起入栈。
    节点
    typedef struct BinTreeNode
    {
    ElemType data;
    struct BinTreeNode *leftChild;
    struct BinTreeNode *rightChild;
    }BinTreeNode;

    入栈的点

    typedef struct StkNode{BinTreeNode *ptr;Tag          tag;}StkNode;

    -遍历过程

    1. 首先得到这个树的根节点,然后将树的根节点及其左孩子入栈,直到这个树的左孩子是空。
    2. 取出栈顶元素,判断是左标志还是右标志。如果是左标志,则将其该为右标志然后继续入栈,且下次操作它的右孩子,是右标志输出
    3. 栈空时结束
  • 代码

void PostOrder(BinTreeNode *t){    if(t != NULL){        SeqStack st;  //定义一个栈        InitStack(&st); //初始化栈        BinTreeNode *p; //定义一个指针,指向一个        StkNode sn;  //定义了一个结构体,其中包含了节点和左右标志位        do{            while( t != NULL){  //根节点不为空的时候                sn.ptr = t;  //prt指向根节点                sn.tag = L;  //节点设置为左标志                Push(&st, sn); //入栈                t = t->leftChild;  //一直入栈直到左孩子为空            }            bool flag = true;  //定义一个开始标志是true            while(flag && !IsEmpty(&st)){                GetTop(&st, &sn);  //得到栈顶元素                Pop(&st);       //弹出栈顶元素                p = sn.ptr;     //p指向了刚弹出的栈顶元素,因为将要对这个元素进行操作。                switch(sn.tag){                case L:                    sn.tag = R;  //从左边返回的话,将标志改成右边并且入栈                    Push(&st, sn);                    flag = false;                    t = p->rightChild;  //操作它的右孩子                    break;                case R:                    printf("%c ", p->data); //此时t的值还是null,代表本层结束了,需要操作上一层                    break;                }            }        }while(!IsEmpty(&st));    }}

中序遍历

  • 遍历过程

    • 首先得到树的根节点,根节点入栈,且其左孩子一直入栈,直到左孩子的左孩子是空。
    • 输出左孩子的值
    • 左孩子还有右孩子,将右孩子入栈,将这个右孩子作为新的根节点重复步骤1
  • 代码如下

void InOrder(BinTreeNode *t){    if(t != NULL)//头结点如果不是空,才可以遍历    {        //初始化栈        SeqStack st; //定义一个栈        InitStack(&st); //初始化栈        BinTreeNode *p = NULL;//指向栈顶元素        Push(&st, t); //根节点入栈        while(!IsEmpty(&st))//非空        {            while(t != NULL && t->leftChild != NULL){                Push(&st, t->leftChild);//这个节点的左孩子入栈                t = t->leftChild;   //一直向左走            }            GetTop(&st, &p);//得到最左边的点            Pop(&st);//探出栈顶元素            printf("%c ", p->data);            if(p->rightChild != NULL){                t = p->rightChild;                if(t != NULL)                    Push(&st, t);//右子树入栈,开始新的一轮。            }        }    }}

先序遍历

  • 遍历过程
    - 树的根节点入栈
    - 输出栈顶元素的值,并且将·其根节点的右孩子入栈,左孩子入栈。
    - 栈分空时重复上一步骤

  • 代码

void PreOrder_1(BinTreeNode *t){    if(t != NULL){        SeqStack st ;        InitStack(&st);        BinTreeNode *p;        //将头结点入栈        Push(&st, t);        while(!IsEmpty(&st)){            GetTop(&st, &p);            Pop(&st);            printf("%c ", p->data);            if(p->rightChild != NULL)                Push(&st,p->rightChild);            if(p->leftChild != NULL)                Push(&st,p->leftChild);        }    }}
0 0
原创粉丝点击