由前序和中序遍历结果构建二叉树

#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;
}

非递归算法。
posted @ 2010-01-17 20:56  明之道  阅读(4800)  评论(0编辑  收藏  举报