二叉樹的主要遍歷方式有先序遍歷、中序遍歷、後序遍歷和層次遍歷。
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;
}
運行結果:
以下圖爲例輸入(其中空結點用“#”表示),輸入的字符串如下: