一、结构体
typedef struct BiTNode{
Elemtype data;
struct BiTNode *lchilde, *rchild;
}BiTNode,*BiTree;
二、二叉树递归遍历
1、先序递归遍历
void preOrder(BiTree T){
if(T==NULL)
return;
else{
printf("%d",T->data);
preOrder(T->lchild);
preOrder(T->rchild);
}
}
2、中序递归遍历
void InOrder(BiTree T){
if(T==NULL)
return ;
else{
InOrder(T->lchilde);
print("%d", T->data);
InOrder(T->rchild);
}
}
3、后序递归遍历
void postOrder(Bitree T){
if(T==NULL)
return;
else{
postOrder(T->lchild);
postOrder(T->rchild);
printf("%d",T->data);
}
}
三、递归遍历练习
1、利用递归计算二叉树中所有结点的个数
- 使用全局变量
int n=0;
void Count(BiTree T){
if(T=NULL)
return;
else{
n++;
Count(T->lchild);
Count(T->rchild);
}
}
- 使用局部变量
int Count(BTree T){
int l,r;//l,r是局部变量
if(T==NULL)
return 0;
else{
l=Count(T->lchild);
r=Count(T->rchild);
return l+r+1;
}
}
2、利用递归计算二叉树中所有叶子结点的个数
- 全局变量
int n=0;//n是全局变量
void Count(BiTree T){
if(T=NULL)
return;
else{
if(T->lchild==NULL && T->rchild==NULL)//如果左右孩子都为空,则为叶子结点
n++;
Count(T->lchild);
Count(T->rchild);
}
}
- 局部变量
int Count(BiTree T){
int l,r;
if(T==NULL)
return 0;
else if(T->lchild==NULL && T->rchild==NULL)
return 1;
else{
l=Count(T->lchild);
r=Count(T->rchild);
return l+r;
}
}
3、利用递归计算二叉树中所有双分支结点个数(还需要再看一下)
int Count(BiTree T){
int l,r;
if(T=NULL)
return 0;
else if(T->lchild!=NULL && T->rchild!=NULL)
return l+r+1;
else{
l=T->lchild;
r=T->rchild;
return l+r;
}
}
四、非递归算法
1、先序非递归
void preOrder(BiTree T){
Stack s;
Initstack(s);//初始化栈
BiTree p=T;//定义遍历指针
while(p!=NULL || !IsEmpty(s)){
if(p!=NULL){
printf("%d",p->data);
push(s,p);
p=p->lchild;
}
else{
pop(s,p);//把栈顶元素弹出,并让p指向它
p=p->rchild;
}//else
}//while
}//void
2、非递归中序(左根右)
一直遍历到最左边,才打印
void InOrder(BiTree T){
Stack s;
Initstack(s);//初始化栈
BiTree p=T;//定义遍历指针
while(p!=NULL || !IsEmpty(s)){
if(p!=NULL){
push(s,p);//入栈
p=p->lchild;//访问左子树
}
else{
pop(s,p);//把栈顶元素弹出,并让p指向它
printf("%d",p->data);
p=p->rchild;//访问右子树
}//else
}//while
}//void
3、非递归后序(左右根)
后序会返回两次根,第一次返回根是遍历完左子树之后,为了去遍历右子树;第二次返回根是遍历完右子树之后,为了去遍历根
因此要定义一个记录指针r,用于标记上一个被访问的结点;且在返回根之前判断是为了去遍历右子树,还是为了去遍历根.
每次出栈访问完一个结点就相当于遍历完以该结点为根的子树,需要将p置NULL
void postOrder(BiTree T){
Stack s;
InitStack(s);//初始化栈
BiNode *p=T;
BiNode *r=NULL;//标记上一个被访问的结点
while(p!=NULL || !IsEmpty(s)){
if(p!=NULL){
push(s,p);
p=p->lchild;
}
else{
GetTop(s,p);//读栈顶指针,让p指向栈顶结点(非出栈)
if(p->rchild!=NULL && p->rchild!=r)//若右子树存在,且未被访问过
p=p->rchild;
else{
pop(s,p);//将该结点弹出
printf("%d",p->data);
r=p;//记录最近访问过的结点
p=NULL;//结点访问完之后,重置p指针
}//else
}//else
}//while
}//void
4、层序遍历
void LevelOrder(BiTree T){
InitQueue(Q);
BiTree p;
EnQueue(Q,T);//将根节点入队
while(!IsEmpty(Q)){//队列不空则循环
DeQueue(Q,p);//队头结点出队
printf("%d",p->data);
if(p->lchild!=NULL)
EnQueue(Q,p->lchild);
if(p->rchild!=NULL)
EnQueue(Q,p->rchild);
}
}
五、练习
1、要求二叉树按照二叉链表存储,写一个判别二叉树是否为完全二叉树的算法
bool Is_wqtree(BiTree T){
IniiQueue(Q);
EnQueue(Q,T);
BiTree p;
while(!IsEmpty(Q)){
DeQueue(Q,p);
if(p!=NULL){
EnQueue(Q,p->lchild);
EnQueue(Q,p->rchild);
}
else{
while(!IsEmpty(Q)){
DeQueue(Q,p);
if(p!=NULL)
return false;
}//while
}else
}//while
return true;
}//bool