二叉树的层次建树
如何层次建立一颗二叉树呢?假设我们需要建一棵树。
这棵树层次遍历得到的序列是: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 }