zoukankan      html  css  js  c++  java
  • 由前序和中序遍历结果构建二叉树

    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>

    #define N    50

    struct Node    /* 树结点类型 */
    {
        char         info;    /* 数据域 */
        struct Node*    parent;    /* 父结点 */
        struct Node*     lchild;    /* 左孩子结点 */
        struct Node*    rchild;    /* 右孩子结点 */
    };
    typedef struct Node* PNode;

    struct Stack        /* 栈结点类型 */
    {
        char*    pre;
        char*    in;
        int    n;
        PNode    parent;
    };


    int myIndex(char seq[],char c)    /* 查找c在seq中的位置,不存在则返回-1 */
    {
        int i;
        for (i = 0;seq[i] != '\0';i++)
        {
            if (seq[i] == c)
            {
                return i;
            }
        }
        return -1;
    }


    /* 创建一棵树,其中pre是前序遍历的结果,in是中序遍历的结果,n是结点总数,parent是所建的树的父结点 */
    /* 如果结点数大于0,则创建一个结点并返回指向这个结点的指针,如果等于0,则返回NULL */
    /* 具体算法请参照二叉树的前序遍历的非递归算法 */
    PNode creattree(char pre[],char in[],int n,PNode parent)
    {
        PNode p;
        struct Stack s[N],t;    /* 用来存储参数的栈 */
        int top = 0;        /* 栈顶指针,值为0的时候,栈为空 */
        int i;
        PNode head = NULL;    /* 用来返回的根结点 */
        int done = 0;    /* 标记树有没有完全建立起来,初始化为假 */
        
        while (!done)    /* 如果树没有建立起来,则要继续进入建立 */
        {
            
            while (n != 0)        /* n的值不为0,也就是pre和in中都至少还有一个元素的时候 */
            {
                i = myIndex(in,pre[0]);        /* 确定pre的第一个元素,就是父结点在中序遍历结果中的位置 */
                p = (PNode)(malloc(sizeof(struct Node)));    /* 建立一个结点 */
                p->info = pre[0];
                
                p->parent = parent;
                p->lchild = NULL;
                p->rchild = NULL;
                if (parent != NULL)    /* 当结点的父结点不是空值时,就把parent的左孩子值改成p */
                {
                    parent->lchild = p;
                }
                else        /* 如果为空时 */
                {
                    head = p;    /* 那么这个结点就是根结点 */
                }
                
                if (n - i - 1 != 0)    /* 只有前序遍历和中序遍历结果都有元素时,才入栈 */
                {
                    
                    t.pre = pre + i + 1;    /* 右子树的前序遍历的结果 */
                    t.in  = in  + i + 1;    /* 右子树的中序遍历的结果 */
                    t.n   = n   - i - 1;    /* 右子树的结点个数 */
                    t.parent = p;        /* 右子树的父结点就是当前结点 */
                    s[++top] = t;        /* 入栈 */
                }
                
                
                pre = pre + 1;        /* 右子树的前序遍历的结果,中序遍历的结果不变 */
                n = i;            /* 只是结点个数减少而已 */
                parent = p;        /* 右子树的父结点就是当前结点 */
            }
            
            
            if (top != 0)        /* 当栈不空时,也就是至少还有一个子树的右子树没有建立 */
            {
                t = s[top--];    /* 出栈 */
                pre = t.pre;
                in  = t.in;
                n   = t.n;
                parent = t.parent;
                
                
                
                i = myIndex(in,pre[0]);
                p = (PNode)(malloc(sizeof(struct Node)));
                p->info = pre[0];
                p->parent = parent;
                p->lchild = NULL;
                p->rchild = NULL;

                if (parent != NULL)
                {
                    parent->rchild = p;    /* 注意,现在是在建立右子树 */
                }
                else
                {
                    head = p;
                }
                
                if (n - i - 1 != 0)
                {
                    
                    t.pre = pre + i + 1;
                    t.in  = in  + i + 1;
                    t.n   = n   - i - 1;
                    t.parent = p;
                    s[++top] = t;
                }
                
                pre = pre + 1;
                n = i;
                parent = p;
            }
            else        /* 栈空了,也就是建立起了这棵树 */
            {
                done = 1;
            }
        }
        return head;
    }


    /* 前序遍历 */
    void pre_order(PNode root)
    {
        if (root != NULL)
        {
            printf("%c ",root->info);
            pre_order(root->lchild);
            pre_order(root->rchild);
        }
    }

    /* 中序遍历 */
    void in_order(PNode root)
    {
        if (root != NULL)
        {
            in_order(root->lchild);
            printf("%c ",root->info);
            in_order(root->rchild);
        }
    }

    /* 后序遍历 */
    void post_order(PNode root)
    {
        if (root != NULL)
        {
            post_order(root->lchild);
            post_order(root->rchild);
            printf("%c ",root->info);
        }
    }

    int main(void)
    {
        PNode root;
        char pre[N];
        char in[N];
        
        printf("请输入前序遍历结果:");
        scanf("%s",pre);
        printf("请输入中序遍历结果:");
        scanf("%s",in);
            
        /* 建树 */
        root = creattree(pre,in,strlen(pre),NULL);
        
        printf("\n前序遍历结果:\n");
        pre_order(root);
        printf("\n中序遍历结果:\n");
        in_order(root);
        printf("\n后序遍历结果:\n");
        post_order(root);
        printf("\n");
        return 0;
    }

    非递归算法。
  • 相关阅读:
    SpringCloud整合过程中jar依赖踩坑经验
    spring-boot-starter-parent的主要作用
    配置Setting.xml文件提高maven更新下载jar包速度
    剑指Offer-编程详解-二维数组中的查找
    Git 拉取Gitee仓库报错:“fatal: unable to access ''": Failed to connect to 127.0.0.1 port 1080: Connection refused”
    SpringBoot整合mybatis——配置mybatis驼峰命名规则自动转换
    SpringBoot 整合 Mybatis + Mysql——XML配置方式
    ES+open-falcon之nginx状态码监控报警自动化
    zabbix告警邮件美化
    基于Jenkins+Gitlab的自动化部署实战
  • 原文地址:https://www.cnblogs.com/ITEagle/p/1650138.html
Copyright © 2011-2022 走看看