实现思路:
1. 构造辅助队列以实现层次建树。实现二叉树的链式表示时,先申请新结点再将结点入队列,各结点依次出队列并放入合适的左右孩子处。
2. 前序、中序、后序遍历时采用递归思想。
3. 可复用前面实现队列时所写的代码,使用头文件简化代码。层次遍历时采用了这一写法。
练习:
实现二叉树层次建树,进行前序遍历、中序遍历、后序遍历、层序遍历并打印输出。
1. function.h头文件
#include <stdio.h>
#include <stdlib.h>
typedef char BiElemType;
typedef struct BiTNode{
BiElemType c;
struct BiTNode *lchild;
struct BiTNode *rchild;
}BiTNode,*BiTree;
//tag结构体是辅助队列使用的
typedef struct tag{
BiTree p;//树的某一个结点的地址值
struct tag *pnext;
}tag_t,*ptag_t;
typedef BiTree ElemType;
typedef struct LinkNode{
ElemType data;
struct LinkNode *next;
}LinkNode;
typedef struct{
LinkNode *front,*rear;//链表头,链表尾,也可以称作队头,队尾
}LinkQueue;//先进先出
//队列初始化,使用带头结点的链表
void InitQueue(LinkQueue &q);
//判断队列是否为空
bool IsEmpty(LinkQueue &q);
//入队
void EnQueue(LinkQueue &q,ElemType elem);
//出队
void DeQueue(LinkQueue &q,ElemType &element);
2. queue.cpp文件(代码复用)
#include "function.h"
//队列初始化,使用带头结点的链表
void InitQueue(LinkQueue &q){
q.front =q.rear=(LinkNode*)malloc(sizeof(LinkNode));//头和尾指向同一个结点
q.front->next = NULL;//头结点的next指针 为NULL
}
//判断队列是否为空
bool IsEmpty(LinkQueue &q){
if(q.front == q.rear){
return true;
}else{
return false;
}
}
//入队
void EnQueue(LinkQueue &q,ElemType elem){
LinkNode *pnew = (LinkNode*)malloc(sizeof(LinkNode));
pnew->data=elem;
pnew->next=NULL;//初始化next,链表结束标志,不能忘!!!
q.rear->next=pnew;//尾部入队,尾指针指向pnew
q.rear=pnew;//更新尾指针
}
//出队
void DeQueue(LinkQueue &q,ElemType &element){
if(IsEmpty(q)){//判空
// printf("DeQueue false\n");
return;
}
LinkNode *p=q.front->next;//拿到第一个结点,存入p
element=p->data;//获取要出队的元素值
q.front->next=p->next;//让第一个结点断链
if(q.rear==p){
q.rear=q.front;
}
free(p);
// printf("DeQueue element %d\n", element);
}
3. 前序遍历
//前序遍历,先序遍历,深度优先遍历,递归思想
void PreOrder(BiTree p){
if(NULL != p) {
printf("%c", p->c);
PreOrder(p->lchild);//打印左子树
PreOrder(p->rchild);//打印右子树
}
}
4. 中序遍历
//中序遍历
void InOrder(BiTree p){
if(NULL != p) {
InOrder(p->lchild);
printf("%c", p->c);
InOrder(p->rchild);
}
}
5. 后序遍历
//后序遍历
void PostOrder(BiTree p){
if(NULL != p) {
PostOrder(p->lchild);
PostOrder(p->rchild);
printf("%c", p->c);
}
}
6. 层序遍历
//层次遍历,层序遍历,广度优先遍历
void LevelOrder(BiTree T){
LinkQueue Q;
InitQueue(Q);
BiTree p;//存储出队的结点
EnQueue(Q,T);//把树根入队
while(!IsEmpty(Q)){
DeQueue(Q,p);
putchar(p->c);//等价于printf("%c",c);
if(p->lchild){
EnQueue(Q,p->lchild);
}
if(p->rchild){
EnQueue(Q,p->rchild);
}
}
}
7. 主函数,包括二叉树建树与遍历结果打印
int main() {
BiTree pnew;//申请一个树的新结点
BiTree tree=NULL;//代表树,指向树根,不分带不带头结点
char c;
ptag_t phead=NULL,ptail=NULL,listpnew=NULL,pcur;
//输入abcdefghij
while(scanf("%c",&c)){
if(c=='\n'){
break;//读取到换行就结束
}
//calloc申请的空间大小是两个参数直接相乘,并对空间进行初始化,赋值为0
pnew = (BiTree)calloc(1,sizeof(BiTNode));
pnew->c=c;
//给队列结点申请空间
listpnew = (ptag_t)calloc(1,sizeof (tag_t));
listpnew->p=pnew;
//如果是树的第一个结点
if(NULL == tree){
tree=pnew;//tree指向树的根结点
phead=listpnew;//第一个结点是队列头,也是队列尾
ptail=listpnew;
pcur=listpnew;//pcur指向要进入树的父亲元素
}else{
//让元素先入队列
ptail->pnext=listpnew;
ptail=listpnew;
//将结点放入树中
if(NULL == pcur->p->lchild){
pcur->p->lchild=pnew;//pcur->p左孩子为空,放入左孩子
}else if(NULL == pcur->p->rchild){
pcur->p->rchild=pnew;//pcur->p右孩子为空,放入右孩子
pcur=pcur->pnext;//当前结点左右孩子都有了,pcur指向下一个结点
}
}
}
printf("PreOrder:\t");
PreOrder(tree);
printf("\nInOrder:\t");
InOrder(tree);
printf("\nPostOrder:\t");
PostOrder(tree);
printf("\nLevelOrder:\t");
LevelOrder(tree);
printf("\n");
return 0;
}
8. 测试

该博客主要介绍用C语言实现二叉树的建树与遍历。实现思路包括构造辅助队列层次建树,前、中、后序遍历采用递归思想,复用队列代码简化层次遍历。练习部分实现了二叉树层次建树,并进行前序、中序、后序、层序遍历,最后打印结果并测试。
&spm=1001.2101.3001.5002&articleId=133956649&d=1&t=3&u=d7b25cac2fc44172ade3a750f5b61ea0)
5417

被折叠的 条评论
为什么被折叠?



