第十一周项目1--(2)二叉树构造算法的验证--由先序序列和中序序列构造二叉树

问题及代码:

/*    
*烟台大学计算机与控制工程学院     
*作    者:刘倩    
*完成日期:2016年11月4日 
*问题描述:任何n(n≥0)个不同节点的二叉树,都可由它的中序序列和先序序列唯一地确定。 
*/  
(1)btree.h代码

#define MaxSize 100  
typedef char ElemType;  
typedef struct node  
{  
    ElemType data;              //数据元素  
    struct node *lchild;        //指向左孩子  
    struct node *rchild;        //指向右孩子  
} BTNode;  
void CreateBTNode(BTNode *&b,char *str);        //由str串创建二叉链  
BTNode *FindNode(BTNode *b,ElemType x);     //返回data域为x的节点指针  
BTNode *LchildNode(BTNode *p);  //返回*p节点的左孩子节点指针  
BTNode *RchildNode(BTNode *p);  //返回*p节点的右孩子节点指针  
int BTNodeDepth(BTNode *b); //求二叉树b的深度  
void DispBTNode(BTNode *b); //以括号表示法输出二叉树  
void DestroyBTNode(BTNode *&b);  //销毁二叉树  
BTNode *CreateBT1(char *pre,char *in,int n);  
(2)btree.cpp代码

#include <stdio.h>  
#include <malloc.h>  
#include "btree.h"  
  
void CreateBTNode(BTNode *&b,char *str)     //由str串创建二叉链  
{  
    BTNode *St[MaxSize],*p=NULL;  
    int top=-1,k,j=0;  
    char ch;  
    b=NULL;             //建立的二叉树初始时为空  
    ch=str[j];  
    while (ch!='\0')    //str未扫描完时循环  
    {  
        switch(ch)  
        {  
        case '(':  
            top++;  
            St[top]=p;  
            k=1;  
            break;      //为左节点  
        case ')':  
            top--;  
            break;  
        case ',':  
            k=2;  
            break;                          //为右节点  
        default:  
            p=(BTNode *)malloc(sizeof(BTNode));  
            p->data=ch;  
            p->lchild=p->rchild=NULL;  
            if (b==NULL)                    //p指向二叉树的根节点  
                b=p;  
            else                            //已建立二叉树根节点  
            {  
                switch(k)  
                {  
                case 1:  
                    St[top]->lchild=p;  
                    break;  
                case 2:  
                    St[top]->rchild=p;  
                    break;  
                }  
            }  
        }  
        j++;  
        ch=str[j];  
    }  
}  
BTNode *FindNode(BTNode *b,ElemType x)  //返回data域为x的节点指针  
{  
    BTNode *p;  
    if (b==NULL)  
        return NULL;  
    else if (b->data==x)  
        return b;  
    else  
    {  
        p=FindNode(b->lchild,x);  
        if (p!=NULL)  
            return p;  
        else  
            return FindNode(b->rchild,x);  
    }  
}  
BTNode *LchildNode(BTNode *p)   //返回*p节点的左孩子节点指针  
{  
    return p->lchild;  
}  
BTNode *RchildNode(BTNode *p)   //返回*p节点的右孩子节点指针  
{  
    return p->rchild;  
}  
int BTNodeDepth(BTNode *b)  //求二叉树b的深度  
{  
    int lchilddep,rchilddep;  
    if (b==NULL)  
        return(0);                          //空树的高度为0  
    else  
    {  
        lchilddep=BTNodeDepth(b->lchild);   //求左子树的高度为lchilddep  
        rchilddep=BTNodeDepth(b->rchild);   //求右子树的高度为rchilddep  
        return (lchilddep>rchilddep)? (lchilddep+1):(rchilddep+1);  
    }  
}  
void DispBTNode(BTNode *b)  //以括号表示法输出二叉树  
{  
    if (b!=NULL)  
    {  
        printf("%c",b->data);  
        if (b->lchild!=NULL || b->rchild!=NULL)  
        {  
            printf("(");  
            DispBTNode(b->lchild);  
            if (b->rchild!=NULL) printf(",");  
            DispBTNode(b->rchild);  
            printf(")");  
        }  
    }  
}  
void DestroyBTNode(BTNode *&b)   //销毁二叉树  
{  
    if (b!=NULL)  
    {  
        DestroyBTNode(b->lchild);  
        DestroyBTNode(b->rchild);  
        free(b);  
    }  
}  
BTNode *CreateBT1(char *pre,char *in,int n)  
/*pre存放先序序列,in存放中序序列,n为二叉树结点个数, 
本算法执行后返回构造的二叉链的根结点指针*/  
{  
    BTNode *s;  
    char *p;  
    int k;  
    if (n<=0) return NULL;  
    s=(BTNode *)malloc(sizeof(BTNode));     //创建二叉树结点*s  
    s->data=*pre;  
    for (p=in; p<in+n; p++)                 //在中序序列中找等于*ppos的位置k  
        if (*p==*pre)                       //pre指向根结点  
            break;                          //在in中找到后退出循环  
    k=p-in;                                 //确定根结点在in中的位置  
    s->lchild=CreateBT1(pre+1,in,k);        //递归构造左子树  
    s->rchild=CreateBT1(pre+k+1,p+1,n-k-1); //递归构造右子树  
    return s;  
}  
(3)main.cpp代码

#include<stdio.h>  
#include"btree.h"  
int main()  
{  
     ElemType pre[]="ABDGCEF",in[]="DGBAECF";  
    BTNode *b1;  
    b1=CreateBT1(pre,in,7);  
    printf("b1:");  
    DispBTNode(b1);  
    printf("\n");  
    return 0;  
  
}  
运行结果:



知识点总结:

任何n(n≥0)个不同节点的二叉树,都可由它的中序序列和先序序列唯一地确定。

学习心得:

代码还是写不出来。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 先序遍历的第一个节点一定是根节点,根据这个特点,我们可以在中序遍历中找到根节点的位置。根据中序遍历的性质,根节点的左边是左子树的中序遍历,右边是右子树的中序遍历。同样地,先序遍历的第二个节点一定是左子树的根节点,根据这个特点,我们可以在先序遍历中找到左子树的根节点。右子树的根节点也可以通过先序遍历找到。 有了这些信息,我们可以递归地构造二叉树。具体地,我们先根据先序遍历的第一个节点创建根节点,然后在中序遍历中找到根节点的位置,根据这个位置将中序遍历分成左右两个部分。左边部分是左子树的中序遍历,右边部分是右子树的中序遍历。同样地,在先序遍历中,根据左子树的根节点和右子树的根节点,将先序遍历分成左右两个部分。左边部分是左子树的先序遍历,右边部分是右子树的先序遍历。然后递归地构造左子树和右子树即可。 具体实现可以参考下面的代码: ``` class TreeNode: def __init__(self, val=, left=None, right=None): self.val = val self.left = left self.right = right def buildTree(preorder, inorder): if not preorder or not inorder: return None root_val = preorder[] root = TreeNode(root_val) root_index = inorder.index(root_val) left_inorder = inorder[:root_index] right_inorder = inorder[root_index+1:] left_preorder = preorder[1:1+len(left_inorder)] right_preorder = preorder[1+len(left_inorder):] root.left = buildTree(left_preorder, left_inorder) root.right = buildTree(right_preorder, right_inorder) return root ``` 其中,preorder和inorder分别表示先序遍历和中序遍历的列表。函数返回构造出的二叉树的根节点。 ### 回答2: 1. 算法说明: 由先序序列中序序列可以唯一确定一棵二叉树。因此我们可以通过先序序列中序序列构造出对应的二叉树。具体的实现步骤如下: 2. 算法实现: Step 1:用先序序列的第一个元素建立根节点。 Step 2:在中序序列中找到根节点的位置,以此将中序序列分为左右两个子序列。 Step 3:在先序序列中找到对应中序序列中左子序列的最后一个元素,建立为根节点的左子节点。 Step 4:通过递归,在左子树的先序序列中序序列中重复步骤1、2、3,构建出左子树。 Step 5:在先序序列中序序列中分别找到对应右子序列的第一个元素,建立为根节点的右子节点。 Step 6:通过递归,在右子树的先序序列中序序列中重复步骤1、2、3、5、6,构建出右子树。 Step 7:返回根节点作为结果。 3. 复杂度分析 该算法的时间复杂度为O(n),其中n为二叉树的节点数。因为在每次递归中,我们都需要在中序序列中寻找根节点位置,这需要O(n)的时间复杂度。而每个节点恰好只被访问一次,因此总的时间复杂度为O(n)。 同时,该算法的空间复杂度也为O(n),因为我们需要开辟O(n)的空间存储整棵二叉树。 ### 回答3: 由先序中序序列构造二叉树是一道经典的算法问题。这个问题的实现需要对二叉树结构、二叉树遍历方式、递归思想等知识点有深入的了解。 先序序列是指先遍历根节点,再遍历左子树,最后遍历右子树。中序序列是指先遍历左子树,再遍历根节点,最后遍历右子树。因此,根据先序中序序列,我们可以确定二叉树的根节点和左右子树的先序中序序列。 具体的实现步骤如下: 1. 从先序序列中取出第一个元素作为根节点。 2. 在中序序列中找到根节点的位置,该位置左边的元素构成二叉树的左子树中序序列,右边的元素构成二叉树的右子树中序序列。 3. 在先序序列中,从第二个元素开始,取出与左子树中序序列相同数量的元素,这些元素构成二叉树的左子树先序序列,剩下的元素构成二叉树的右子树先序序列。 4. 对左子树进行递归构造,得到左子树的根节点,并将其设为根节点的左子节点。 5. 对右子树进行递归构造,得到右子树的根节点,并将其设为根节点的右子节点。 6. 返回根节点。 需要注意的是,如果先序序列中序序列为空,那么返回空节点。如果先序序列中序序列的长度不相等,那么抛出错误信息。 在实现过程中,需要进行递归操作,因此需要清楚递归的终止条件、递归的参数和递归的返回值。同时,需要对二叉树节点的定义有清晰的认识,包括节点的值、左节点和右节点等属性。 实现由先序中序序列构造二叉树算法,不仅考察了对二叉树的理解,还考察了递归思想和代码能力。如果能够熟练地掌握这个算法,对于解决其他与二叉树相关的问题也会有帮助。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值