二叉树是树结构中最容易实现的数据结构,本节介绍二叉树的各种遍历实现形式,分为先序,中序,后序,以及层序遍历。层次遍历是基于树的层次特性确定的次序规则,而先/中/后/序遍历是基于树的递归特性确定的次序规则。
1.先中后序遍历实现
// 二叉树的链式存储及三种递归遍历方式
#include <stdio.h>
#include <stdlib.h>
typedef struct BiTNode{
char data; // 数据域
struct BiTNode *lchild,*rchild; // 左右孩子指针
}BiTNode,*BiTree;
void CreateBiTree_Pre(BiTree &T){ // 先序遍历创建二叉树
char s;
scanf("%c\n",&s);
if(s=='#')
T = NULL; // 控制左孩或右孩
else{
T = (BiTree)malloc(sizeof(BiTNode));// 新建结点
T->data = s;
CreateBiTree_Pre(T->lchild);
CreateBiTree_Pre(T->rchild);
}
}
void PreOrder(BiTree T){ //先序遍历
if(T!=NULL){
printf("%c\n",T->data);
PreOrder(T->lchild);
PreOrder(T->rchild);
}
}
void InOrder(BiTree T){ //中序遍历
if(T!=NULL){
InOrder(T->lchild);
printf("%c\n",T->data);
InOrder(T->rchild);
}
}
void PostOrder(BiTree T){ //后序遍历
if(T!=NULL){
PostOrder(T->lchild);
PostOrder(T->rchild);
printf("%c\n",T->data);
}
}
int treeDepth(BiTree T){ // 递归求树的深度
if(T == NULL)
return 0;
else{
int l = treeDepth(T->lchild);
int r = treeDepth(T->rchild);
return l>r ? l+1 : r+1; // 树的深度=Max(左子树深度,右子树深度)+1
}
}
// test
int main(){
BiTree T;
CreateBiTree_Pre(T);
InOrder(T);
printf("---this is divide line---\n");
PostOrder(T);
printf("the Depth is:\n");
printf("%d",treeDepth(T));
return 0;
}
2. 层序遍历实现
// 二叉树的层序遍历,使用辅助链队列实现
#include <stdio.h>
#include <stdlib.h>
typedef struct BiTNode{
char data; // 数据域
struct BiTNode *lchild,*rchild; // 左右孩子指针
}BiTNode,*BiTree;
typedef struct LinkNode{
BiTNode * data; //储存指针而不是结点
struct LinkNode *next;
}LinkNode;
typedef struct{
LinkNode *front,*rear; //队头队尾
int size;
}LinkQueue;
void InitQueue(LinkQueue &Q){
// 初始时 front,rear都指向null
Q.front=NULL;
Q.rear=NULL;
Q.size = 0;
}
bool IsEmpty(LinkQueue Q){
if(Q.size == 0)
return true;
else
return false;
}
// 入队
void EnQueqe(LinkQueue &Q, BiTree x){
LinkNode *s=(LinkNode *)malloc(sizeof(LinkNode));
s->data = x;
s->next = NULL;
if(Q.front==NULL){// 当空队列入队第一个元素时
Q.front=s;
Q.rear=s;
}else{
Q.rear->next = s;// 新结点插入到rear之后
Q.rear = s;// rear指向队尾元素
}
Q.size++;
}
bool DeQueue(LinkQueue &Q,BiTree &x){
if(Q.front==NULL)// 空队
return false;
LinkNode *q = Q.front;
x = q->data;
Q.front = q->next;
if(Q.rear==q){ // 最后一个结点出队时,修改rear与front指针到null
Q.front=NULL;
Q.rear=NULL;
}
free(q);
Q.size--;
return true;
}
void CreateBiTree_Pre(BiTree &T){ // 先序遍历创建二叉树
char s;
scanf("%c\n",&s);
if(s=='#')
T = NULL; // 控制左孩或右孩
else{
T = (BiTree)malloc(sizeof(BiTNode));// 新建结点
T->data = s;
CreateBiTree_Pre(T->lchild);
CreateBiTree_Pre(T->rchild);
}
}
void PostOrder(BiTree T){ //后序遍历
if(T!=NULL){
PostOrder(T->lchild);
PostOrder(T->rchild);
printf("%c\n",T->data);
}
}
// 层序遍历
void LevelOrder(BiTree T){
LinkQueue Q;
InitQueue(Q); // 初始化辅助队列
EnQueqe(Q,T); //将根节点入队
while(!IsEmpty(Q)){ //队列不空则循环
BiTNode* p = NULL;
DeQueue(Q,p); // 队头结点出队
printf("%c\n",p->data); // 访问出队结点
if(p->lchild!=NULL)
EnQueqe(Q,p->lchild);// 左孩子入队
if(p->rchild!=NULL)
EnQueqe(Q,p->rchild);// 右孩子入队
}
}
int main(){ // test
BiTree T;
CreateBiTree_Pre(T);
PostOrder(T);
printf("the res is:\n");
LevelOrder(T);
return 0;
}