潭影-pjq

二叉树的层次建树

如何层次建立一颗二叉树呢?假设我们需要建一棵树。
这棵树层次遍历得到的序列是:abcdefg
(但是注意,我们只有知道一颗二叉树前/后/层序遍历中的任意一种和中序遍历时,才能唯一确定一颗二叉树,我们在这里是直接给出了树的形状,当然能唯一确定二叉树,但是事实上,只告诉了层序遍历得到的序列,我们没有办法确定树的形状,而以下代码,建出来的树一定是完全二叉树)

 

 

 首先定义二叉树的类型

typedef char ElemType;      //我们在数据域存入字符类型的数据
typedef struct BiTNode {
    ElemType c;//数据域
    struct BiTNode* lchild, * rchild;//左、右孩子的指针
}BiTNode,*BiTree;//在后续操作中,BiTNode强调是一个结点,BiTree强调是一棵树

 

再定义一个辅助链表,用于存放二叉树中各个结点的指针,便于我们建树(这里存放的是指针,而不是整个结点,这样的操作可以省一些内存空间,降低空间复杂度)

typedef struct tag {
    BiTree p;           //某一个结点的指针
    struct tag* pnext;  //下一个结点的指针
}tag_t;  //在后续操作中tag_t强调这是链表中的一个结点

先序遍历

void PreOrder(BiTree T)//先序遍历
{
    if (T != NULL)
    {
        putchar(T->c);
        PreOrder(T->lchild);
        PreOrder(T->rchild);
    }
}

开始建树

int main()
{
    //开始建二叉树
    BiTree T=NULL;//首先声明一棵二叉树,此时二叉树为空
    BiTNode* pnew=NULL;//表示用于存放将要存入树中的元素
    tag_t* phead=NULL; //在后续操作中phead始终指向辅助链表的头部(这个链表没带头结点)
    tag_t* ptail=NULL; //而ptail指向辅助链表的尾部
    tag_t* pcur=NULL;  //pcur表示current,即当前指向当前链表中的一个结点,
                       //——我暂时说不清它指向哪个结点,但是可以确定的是,它不是指向新的结点
    tag_t* listpnew=NULL;//表示新的结点
    char c;//需要被读取的元素
    while (scanf("%c", &c) != EOF) //EOF表示读取结束
    {
        if (c == '\n')  //注意这个判断条件,一般都是"==",而赋值是"="
        {
            break;      //如果c=='\n',跳出读取,因为%c会读取换行符,也就是它会把'\n'当作一个字符
        }
        pnew = (BiTNode*)calloc(1, sizeof(BiTNode));//用于暂存二叉树的新结点
        pnew->c = c;                                //新结点的属于设为读入的元素
        listpnew = (tag_t*)calloc(1, sizeof(BiTNode));//用于将存放二叉树新结点的地址
        listpnew->p = pnew;                           //数据域设为pnew
        if (T == NULL)
        {
            T = pnew;               //树空则填入第一个结点
            phead = listpnew;       //并将phead,ptail,pcur,都指向listpnew
            ptail = listpnew;       //虽然每次读入一个元素这个listpnew一直在变化成一个新的链表结点
            pcur = listpnew;        //但是这个phead指向的地址却不变,相当于又一个链表,phead指向链表头
                                    //ptail指向链表尾
            continue;//一定要加这个continue,表示结束这一次循环,也就是说我们添加了根节点之后,这部分if语句里的代码就不用管了
        }
        else
        {
            ptail->pnext = listpnew; //将新元素插入链表尾部
            ptail = listpnew;        //ptail指向链表尾部
        }
        if (pcur->p->lchild == NULL)//二叉树中的一个结点的左子树为空
        {
            pcur->p->lchild = pnew; //将其左子树填入新结点
        }
        else if (pcur->p->rchild == NULL)//右子树为空
        {
            pcur->p->rchild = pnew;   //将其右子树填入新的结点
            pcur = pcur->pnext; //当左右子树都填入结点之后,表示这个节点的数据域,左右孩子域内都有元素了
                                //那么此时pcur就可以指向下一个链表中的节点了
            //比如层次建树。前三个元素是abc,a是根节点,在a的左孩子填入b,在a的右孩子填入c,那么a就可以功成身退了
            //此时链表中的元素是abc,继而将pur指向结点b,继续在b的左右孩子域填入新结点,依此类推,直到所有元素完全填入
        }
    }
    PreOrder(T);
    //abcdefg
}

 

posted on 2022-05-04 19:56  潭影-pjq  阅读(264)  评论(0编辑  收藏  举报