非递归创建二叉树 先序 中序 后序遍历

思想:用”栈”来消除递归。

主要是建立的过程,刚开始卡到了如果遇到’#’,那么在else中间出栈之后还需要读一个元素,这样在遇到连续的”#”之后,退栈并不能达到合适的位置,最后听了“巅峰”的建议,还是设置了flag,解决了问题,下面解释下建立过程的思想:

1:正常情况下以先序的方式输入串。一个一个字符读取;如果第一个字符不为“#”,先将它入栈,即我们的根。
2:初始化flag = 0,如果没有读到“#”,就开辟节点,获取栈顶元素,将字符存入栈顶元素的lchild,并且将它入栈。
3:要是读到”#”,就将flag = 1;重新读取一个元素,若不为“#”,就将它存入栈顶元素的rchild,然后将flag = 0;如果读到“#”后接下来又读到”#”,那么就出栈一个元素,并且判断当前栈顶的rchild是不是刚才出栈的元素。如果是刚才出栈的元素并且栈不为空,那就说明当前栈顶元素的左右子树都已经建立完毕,那就再出一个,再判断,直到不是才说明我们的将此时根的左边才完全建立好了,要是一直出到栈为空,那就说明完全建立完毕。

下面附上代码:


#include<stdio.h>
#include<stdlib.h>
#include "my_stack.h"

Tree creat(Head);
void PreOrder(Tree,Head);
void InOrder(Tree,Head);
void LastOrder(Tree,Head);

void LastOrder(Tree root,Head head)
{
    Tree q = NULL;
    while(root || head->top != -1 ) {
        if(root) {
            push(head,root);
            root = root->lchild;
        }                                  //每次需要先走到最左边
        else {
            root = gettop(head);
            if((root->rchild == NULL )|| (root->rchild == q)) { //取栈顶判断
                //如果邮孩子为空或者右孩子刚被访问过,说明上一个元素的公恩两个已经结束了,那就访问根,
                root = pop(head);
                printf("%c ",root->data);
                q = root;      //这一步保存当前根的位置,以便下一次判断
                root = NULL;   //下一次直接判断
            }
            else {
                root = root->rchild; //否则左边完毕就往右边走。
            }

        }
    }
}
void InOrder(Tree root,Head head)
{
    while(root || head->top != -1) {
        if(root) {
            push(head,root);
            root = root->lchild;
        }
        else {
            root = pop(head);
            printf("%c ",root->data);
            root = root->rchild;
        }
    }
}
void PreOrder(Tree root,Head head)
{
    while(root || head->top != -1) {
        if(root) {
            printf("%c ",root->data);
            push(head,root);
            root = root->lchild;
        }
        else {
            root = pop(head);
            root = root->rchild;
        }
    }
}
Tree creat(Head head)
{
    Tree p,q;
    Tree root = NULL;
    char ch;
    int flag = 0;
    ch = getchar();
    if(ch == '#') {
        return 0;
    }
    root = (Tree)malloc(sizeof(tree));   //为第一个节点申请空间并且入栈
    p = root;
    p->data = ch;
    push(head,p);
    while(head->top != -1 || ch != '#') {
        ch = getchar();
        if(ch == '#' && flag == 0) {     //如果给右孩子填过值,那下面就走左边
            flag = 1;
        }
        else if(ch == '#' && flag == 1) { //连续读到两个#,那就边判断边将右孩子和栈顶右孩子一样的出栈,
            //说明右边这些部分已经结束                                         
            p = pop(head);
            while(head->top != -1 && gettop(head)->rchild == p) {
                p = pop(head);
            }
        }
        else {
            q = (Tree)malloc(sizeof(tree));
            q->data = ch;
            if(flag == 0) {              //正常情况先访问左边
                p = gettop(head);
                push(head,q);
                p->lchild = q;
            }
            if(flag == 1) {              //要是读到'#'就来这一句。
                p = gettop(head);
                p->rchild = q;
                push(head,q);
                flag = 0;
            }
        }
    }
    return root;
}


int main(int argc,char *argv[])
{
    Tree root = NULL;
    Head head = initstack(head);
    printf("非递归建树:\n");
    root = creat(head);
    printf("非递归先序遍历:\n");
    PreOrder(root,head);
    printf("\n");
    printf("非递归中序遍历:\n");
    InOrder(root,head);
    printf("\n");
    printf("非递归后序遍历:\n");
    LastOrder(root,head);
    printf("\n");

}
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

杨博东的博客

请我喝瓶可乐鼓励下~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值