參考書籍:數據結構(C語言版)嚴蔚敏吳偉民編著清華大學出版社
本文中的代碼可從這裏下載:https://github.com/qingyujean/data-structure
1.動態二叉鏈表存儲即遍歷的實現
1.1.動態二叉鏈表的定義
#include<stdio.h>
#include<stdlib.h>
#define NULL 0
typedef char TElemType;
//動態二叉鏈表
typedef struct BiTNode{
TElemType data;
struct BiTNode *lchild, *rchild;
}BiTNode, *BiTree;
測試用例:
測試按先序序列輸入:abc..de.g..f...#,點號代表空樹,#爲輸入結束符
另外下面的算法有使用到棧的,棧的相關實現如下:
#define MAXSIZE 100
typedef BiTNode* SElemType;
typedef struct SqStack{
SElemType data[MAXSIZE];
int top;//指向棧頂元素
}SqStack;
//初始化空棧
void initStack(SqStack &s){
s.top = 0;
}
//判棧空
bool isEmpty(SqStack s){
if(s.top == 0){
//printf("是空棧\n");//
return true;
}else{
return false;
}
}
//判棧滿
bool isFull(SqStack s){
if(s.top == MAXSIZE){
return true;
}
else{
return false;
}
}
//取棧頂元素
void getTopElem(SqStack s, SElemType &e){
if(!isEmpty(s))
e = s.data[s.top-1];
else
printf("此棧爲空棧,取棧頂元素失敗\n");
}
//入棧
void push(SqStack &s, SElemType e){
if(!isFull(s)){
s.data[s.top] = e;
s.top++;
}else
printf("此棧已滿,入棧操作失敗\n");
}
//出棧
void pop(SqStack &s, SElemType &e){
if(!isEmpty(s)){
e = s.data[s.top-1];
s.top--;
}
else
printf("此棧爲空棧,出棧操作失敗\n");
}
更詳細的棧實現請參見我的另一篇博文:數據結構(5)--棧的定義以及相關操作的實現http://blog.csdn.net/u010366748/article/details/50639195
1.2按先序序列輸入創建二叉樹的遞歸算法
//利用先序序列建立一顆二叉樹,先序序列讀入:'a', 'b', 'c', '.', '.', 'd', 'e', '.', 'g', '.', '.', 'f', '.', '.', '.'
//,'.'代表空樹
//測試用例:abc..de.g..f...#
void createBiTreeByPreOrder(BiTree &T){
//按先序次序輸入二叉樹中節點的值(一個字符),點號字符表示空樹,構造二叉鏈表表示的二叉樹
//注意:若輸入的字符數(不含#號)爲n個,則相應的空樹即點號就應該有n+1個
char ch;
scanf("%c", &ch);
//printf("test:%c\n", ch);
if(ch != '#'){
if(ch == '.'){
T = NULL;
}else{
T = (BiTNode *)malloc(sizeof(BiTNode));
T->data = ch;
createBiTreeByPreOrder(T->lchild);
createBiTreeByPreOrder(T->rchild);
}
}
}
1.3先序遍歷二叉樹的遞歸算法
//先序遍歷打印二叉樹的遞歸算法(根、左、右)
void preOrderPrint(BiTree T){
if(T){
printf("%c ", T->data);
preOrderPrint(T->lchild);
preOrderPrint(T->rchild);
}
}
1.4先序遍歷二叉樹的非遞歸算法
//先序遍歷打印二叉樹的非遞歸算法(根、左、右)
void preOrderPrint2(BiTree T){
SqStack s;
initStack(s);
BiTNode *p = T;
while(p || !isEmpty(s)){
if(p){
printf("%c ", p->data);
push(s, p);
p = p->lchild;
}else{
//printStack(s);
pop(s, p);//棧頂指針(當前層的根節點指針)彈出
p = p->rchild;
}
}
}
演示:
void main(){
BiTree T;
printf("請按先序次序輸入二叉樹各節點的值,以空格表示空樹,以#號結束:\n");
createBiTreeByPreOrder(T);
printf("先序遍歷打印二叉樹:\n");
preOrderPrint(T);
printf("\n");
printf("先序遍歷打印二叉樹(非遞歸算法):\n");
preOrderPrint2(T);
printf("\n");
}
1.5中序遍歷二叉樹的遞歸算法
//中序遍歷打印二叉樹的遞歸算法(左、根、右)
void inOrderPrint(BiTree T){
if(T){
inOrderPrint(T->lchild);
printf("%c ", T->data);
inOrderPrint(T->rchild);
}
}
1.6中序遍歷二叉樹的非遞歸算法
//中序遍歷打印二叉樹的非遞歸算法(左、根、右)
void inOrderPrint2(BiTree T){
SqStack s;
initStack(s);
BiTNode *p = T;
while(p || !isEmpty(s)){
if(p){
push(s, p);
p = p->lchild;
}else{
pop(s, p);//棧頂指針(當前層的根節點指針)彈出
printf("%c ", p->data);
p = p->rchild;
}
}
}
演示:
void main(){
BiTree T;
printf("請按先序次序輸入二叉樹各節點的值,以空格表示空樹,以#號結束:\n");
createBiTreeByPreOrder(T);
printf("中序遍歷打印二叉樹:\n");
inOrderPrint(T);
printf("\n");
printf("中序遍歷打印二叉樹(非遞歸算法):\n");
inOrderPrint2(T);
printf("\n");
}
1.7後序遍歷二叉樹的遞歸算法
//後序遍歷打印二叉樹的遞歸算法(左、右、根)
void postOrderPrint(BiTree T){
if(T){
postOrderPrint(T->lchild);
postOrderPrint(T->rchild);
printf("%c ", T->data);
}
}
1.8後序遍歷二叉樹的非遞歸算法
//後序遍歷打印二叉樹的非遞歸算法(左、右、根)
void postOrderPrint2(BiTree T){
SqStack s;
initStack(s);
BiTNode *p = T;
while(p || !isEmpty(s)){
if(p){
push(s, p);
p = p->lchild;
}else{
BiTNode *top;
getTopElem(s, top);//取得棧頂元素
if(top->data > 0){//棧頂元素的右子樹還沒有被訪問過
p = top->rchild;
top->data = -top->data;//賦右子樹已遍歷標誌
}else{//棧頂元素的右子樹已經訪問過了
printf("%c ", -top->data);
pop(s, top);
//p = NULL;
}
}
}
}
演示:
void main(){
BiTree T;
printf("請按先序次序輸入二叉樹各節點的值,以空格表示空樹,以#號結束:\n");
createBiTreeByPreOrder(T);
printf("後序遍歷打印二叉樹:\n");
postOrderPrint(T);
printf("\n");
printf("後序遍歷打印二叉樹(非遞歸算法):\n");
postOrderPrint2(T);
printf("\n");
}
1.9按層次遍歷二叉樹的非遞歸算法
typedef BiTNode* QElemType;
typedef struct{
QElemType data[20];
int f;//指向隊頭元素
int r;//指向對尾元素的下一個位置
}SqQueue;
//初始化一個空隊列
void initQueue(SqQueue &Q){
Q.f = Q.r = 0;
}
//按層次遍歷(從上到下,從左到右),
void hierarchicalTraversePrint(BiTree T){
//QElemType queue[20];//維護一個順序隊列,用來按層次存放每個實節點,實際上是一個廣度優先搜索
//int f = 0, r = 0;//隊頭隊尾
SqQueue Q;//維護一個順序隊列,用來按層次存放每個實節點,實際上是一個廣度優先搜索
initQueue(Q);
//注意,不能寫成int f, r = 0;否則f沒有被賦值
if(T){
//queue[0] = T;//根節點入隊
Q.data[Q.r] = T;//根節點入隊
Q.r++;
}
while(Q.f != Q.r){
//先將隊頭元素的左孩子依次入隊
if(Q.data[Q.f]->lchild){
Q.data[Q.r] = Q.data[Q.f]->lchild;
Q.r++;
}
//將隊頭元素的右孩子依次入隊
if(Q.data[Q.f]->rchild){
Q.data[Q.r] = Q.data[Q.f]->rchild;
Q.r++;
}
//然後打印(訪問)隊頭元素,並將隊頭元素出隊
printf("%c ", Q.data[Q.f]->data);
Q.f++;//隊頭元素出隊
}
printf("\n");
}
演示:
void main(){
BiTree T;
printf("請按先序次序輸入二叉樹各節點的值,以空格表示空樹,以#號結束:\n");
createBiTreeByPreOrder(T);
printf("按層次遍歷打印二叉樹(非遞歸算法):\n");
hierarchicalTraversePrint(T);
}
2.遍歷二叉樹的應用
2.1求二叉樹的深度
//求二叉樹的深度
int getBiTreeDepth(BiTree T){
if(!T){
return 0;
}
int leftTreeDepth = getBiTreeDepth(T->lchild);
int rightTreeDepth = getBiTreeDepth(T->rchild);
return leftTreeDepth > rightTreeDepth ? (leftTreeDepth+1) : (rightTreeDepth+1);
}
演示:
void main(){
BiTree T;
printf("請按先序次序輸入二叉樹各節點的值,以空格表示空樹,以#號結束:\n");
createBiTreeByPreOrder(T);
int depth = getBiTreeDepth(T);
printf("該二叉樹樹的深度爲%d\n", depth);
}
2.2求二叉樹的結點數
//求二叉樹的節點數
int getBiTreeSize(BiTree T){
if(!T)
return 0;
int leftTreeSize = getBiTreeSize(T->lchild);
int rightTreeSize = getBiTreeSize(T->rchild);
return leftTreeSize + rightTreeSize + 1;
}
演示:
void main(){
BiTree T;
printf("請按先序次序輸入二叉樹各節點的值,以空格表示空樹,以#號結束:\n");
createBiTreeByPreOrder(T);
int size = getBiTreeSize(T);
printf("該二叉樹樹的結點數爲%d\n", size);
}
2.3求二叉樹的葉子節點數
//先序遍歷求葉子節點數
int getBiTreeLeafNodesNum2(BiTree T){
if(T){
if(!T->lchild && !T->rchild)
return 1;
else{
int leftTreeLeafNodesNum = getBiTreeLeafNodesNum2(T->lchild);
int rightTreeLeafNodesNum = getBiTreeLeafNodesNum2(T->rchild);
return leftTreeLeafNodesNum + rightTreeLeafNodesNum;
}
}else{
return 0;
}
}
或者:
//先序遍歷求葉子節點數
void getBiTreeLeafNodesNum(BiTree T, int &count){
if(T){
if(!T->lchild && !T->rchild)
count++;
//else{
getBiTreeLeafNodesNum(T->lchild, count);
getBiTreeLeafNodesNum(T->rchild, count);
//}
}
}
演示:
void main(){
BiTree T;
printf("請按先序次序輸入二叉樹各節點的值,以空格表示空樹,以#號結束:\n");
createBiTreeByPreOrder(T);
int leafNodesNum2 = 0;
leafNodesNum2 = getBiTreeLeafNodesNum2(T);
printf("該二叉樹樹的葉子點數爲%d\n", leafNodesNum2);
}
或者:
void main(){
BiTree T;
printf("請按先序次序輸入二叉樹各節點的值,以空格表示空樹,以#號結束:\n");
createBiTreeByPreOrder(T);
int leafNodesNum = 0;
getBiTreeLeafNodesNum(T, leafNodesNum);
printf("該二叉樹樹的葉子點數爲%d\n", leafNodesNum);
}