二叉树的主要遍历方式有先序遍历、中序遍历、后序遍历和层次遍历。
1.先序遍历
先序遍历的操作过程如下:
如果二叉树为空树,则什么都不做;否则:
(1)访问根节点
(2)先序遍历左子树
(3)先序遍历右子树
对应算法代码如下:
/* 先序遍历 */
/* *p指的是二叉树的根节点 */
void preOrder(BTNode *p) {
if(p!=NULL) {
printf("%c",p->data);// 打印树结点的数据
preOrder(p->lchild);// 先序遍历左子树
preOrder(p->rchild);// 先序遍历右子树
}
}
2.中序遍历
中序遍历的操作过程如下:
如果二叉树为空树,则什么都不做;否则:
(1)中序遍历左子树
(2)访问根节点
(3)中序遍历右子树
对应的算法代码如下:
/* 中序遍历 */
/* *p指的是二叉树的根节点 */
void inOrder(BTNode *p) {
if(p!=NULL) {
inOrder(p->lchild);
printf("%c",p->data);
inOrder(p->rchild);
}
}
3.中序遍历
后序遍历的操作过程如下:
如果二叉树为空树,则什么都不做;否则:
(1)后序遍历左子树
(2)后序遍历右子树
(3)访问根节点
对应的算法代码如下:
/* 后序遍历 */
/* *p指的是二叉树的根节点 */
void postOrder(BTNode *p) {
if(p!=NULL) {
postOrder(p->lchild);
postOrder(p->rchild);
printf("%c",p->data);
}
}
完整代码如下:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<assert.h>
/* 数结构体类型定义*/
typedef struct BTNode {
char data;// 这里默认结点data域为char类型
struct BTNode *lchild;// 左孩子指针域
struct BTNode *rchild;// 右孩子指针域
} BTNode,*BiTree;
/* 根据输入创建二叉树 */
/* 例:ABC##DE##F##GH### */
void CreatBiNode(BTNode **Node) { //此处应注意传递的参数(二重指针)
char data;
scanf("%c", &data);
*Node = (BiTree)malloc(sizeof(BTNode));
if (data == '#') {
*Node = NULL;
} else if ((data != '#') && (*Node)) {
(*Node)->data = data;
(*Node)->lchild = NULL;
(*Node)->rchild = NULL;
CreatBiNode(&(*Node)->lchild);
CreatBiNode(&(*Node)->rchild);
}
}
/* 先序遍历 */
/* *p指的是二叉树的根节点 */
void preOrder(BTNode *p) {
if(p!=NULL) {
printf("%c",p->data);// 打印树结点的数据
preOrder(p->lchild);// 先序遍历左子树
preOrder(p->rchild);// 先序遍历右子树
}
}
/* 中序遍历 */
/* *p指的是二叉树的根节点 */
void inOrder(BTNode *p) {
if(p!=NULL) {
inOrder(p->lchild);
printf("%c",p->data);
inOrder(p->rchild);
}
}
/* 后序遍历 */
/* *p指的是二叉树的根节点 */
void postOrder(BTNode *p) {
if(p!=NULL) {
postOrder(p->lchild);
postOrder(p->rchild);
printf("%c",p->data);
}
}
int main() {
printf("先序输入二叉树(空结点用'#'表示):");
BiTree T=NULL;
CreatBiNode(&T);// 创建二叉树
/* 先序遍历 */
printf("先序遍历:");
preOrder(T);
/* 中序遍历 */
printf("\n中序遍历:");
inOrder(T);
/* 后序遍历 */
printf("\n后序遍历:");
postOrder(T);
return 0;
}
注意:上面创建的二叉树使用的是先序遍历的方式,所以输入字符的时候要按照先序的方式。
注意:空结点用“#”表示,而输入一个先序字符串,然后按回车,创建二叉树完成。
4.层次遍历
如上图,先遍历每一层。第一层是A,第二层是BC,第三层是DEFG,第四层是HI。所以结果为ABCDEFGHI。
图6-10所示为二叉树的层次遍历,即按照箭头所指方向,按照1、2、3、4的层次顺序,对二叉树中各个结点进行访问(此图反映的是自左至右的层次遍历,自右至左的方式类似)。
要进行层次遍历,需要建立一个循环队列。先将二叉树头结点入队列,然后出队列,访问该结点,如果它有左子树,则将左子树的根结点入队:如果它有右子树,则将右子树的根结点入队。然后出队列,对出队结点访问。如此反复,直到队列为空为止。
核心代码:
/* 层次遍历 */
void level(BTNode *p) {
int front,rear;
BTNode *que[maxSize];// 定义一个循环队列,用来记录要访问的层次上的结点
front=rear=0;
BTNode *q;
if(p!=NULL) {
rear=(rear+1)%maxSize;
que[rear]=p;// 根节点入队
while(front!=rear) { // 当队列不空的时候进行循环
front=(front+1)%maxSize;
q=que[front];// 队头结点出队
printf("%c",q->data);// 访问队头结点
if(q->lchild!=NULL) { // 如果左子树不空,则左子树的根节点入队
rear=(rear+1)%maxSize;
que[rear]=q->lchild;
}
if(q->rchild!=NULL) { // 如果右子树不空,则右子树的根节点入队
rear=(rear+1)%maxSize;
que[rear]=q->rchild;
}
}
}
}
完整代码:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<assert.h>
#define maxSize 30
/* 数结构体类型定义*/
typedef struct BTNode {
char data;// 这里默认结点data域为char类型
struct BTNode *lchild;// 左孩子指针域
struct BTNode *rchild;// 右孩子指针域
} BTNode,*BiTree;
/* 根据输入创建二叉树 */
/* 例:ABC##DE##F##GH### */
void CreatBiNode(BTNode **Node) { //此处应注意传递的参数(二重指针)
char data;
scanf("%c", &data);
*Node = (BiTree)malloc(sizeof(BTNode));
if (data == '#') {
*Node = NULL;
} else if ((data != '#') && (*Node)) {
(*Node)->data = data;
(*Node)->lchild = NULL;
(*Node)->rchild = NULL;
CreatBiNode(&(*Node)->lchild);
CreatBiNode(&(*Node)->rchild);
}
}
/* 层次遍历 */
void level(BTNode *p) {
int front,rear;
BTNode *que[maxSize];// 定义一个循环队列,用来记录要访问的层次上的结点
front=rear=0;
BTNode *q;
if(p!=NULL) {
rear=(rear+1)%maxSize;
que[rear]=p;// 根节点入队
while(front!=rear) { // 当队列不空的时候进行循环
front=(front+1)%maxSize;
q=que[front];// 队头结点出队
printf("%c",q->data);// 访问队头结点
if(q->lchild!=NULL) { // 如果左子树不空,则左子树的根节点入队
rear=(rear+1)%maxSize;
que[rear]=q->lchild;
}
if(q->rchild!=NULL) { // 如果右子树不空,则右子树的根节点入队
rear=(rear+1)%maxSize;
que[rear]=q->rchild;
}
}
}
}
int main() {
printf("先序输入二叉树(空结点用'#'表示):");
BiTree T=NULL;
CreatBiNode(&T);// 创建二叉树
/* 层次遍历 */
printf("层次遍历:");
level(T);
return 0;
}
运行结果:
以下图为例输入(其中空结点用“#”表示),输入的字符串如下: