1. 程式人生 > >實驗三:二叉樹的操作(結構轉換,遞迴和非遞迴的先序、中序和後序遍歷,以及層次遍歷,葉子結點和總結點的計數)

實驗三:二叉樹的操作(結構轉換,遞迴和非遞迴的先序、中序和後序遍歷,以及層次遍歷,葉子結點和總結點的計數)

(1)將一棵二叉樹的所有結點儲存在一維陣列中,虛結點用#表示,利用二叉樹性質5,建立二叉樹的二叉連結串列。

(2) 寫出對用二叉連結串列儲存的二叉樹進行先序、中序和後序遍歷的遞迴和非遞迴演算法。

(3)寫出對用二叉連結串列儲存的二叉樹進行層次遍歷演算法。

(4)求二叉樹的所有葉子及結點總數。

//Sinhaeng Hhjian
#include<stdio.h>
#include<string.h> 
#include<stdlib.h>
#define MAX 100005
typedef struct BTNode{
	char data;
	struct BTNode *lchild, *rchild;
}BTNode, *BiTree;

struct Queue{
	BiTree *base;
	int f, r;
};

void InitQueue(Queue &q){
	q.base = (BiTree *)malloc(sizeof(BiTree) * MAX);
	q.f = q.r = 0;
}

void InQueue(Queue &q, BiTree bt){
	q.base[q.r++] = bt;
}

int IsEmpty(Queue q){
	return q.f == q.r? 1:0;
}

void OutQueue(Queue &q, BiTree &bt){
	if(IsEmpty(q)) return ;
	bt = q.base[q.f++];
}
 
void CreatBiTree(BiTree &bt, char *Data, int n){
	Queue Q;
	int Qnum[MAX], f, r, i;
	BiTree p;
	if(n<1){
		bt = NULL;
		return;
	}
	bt = (BiTree)malloc(sizeof(BTNode));
	bt->data = Data[1];
	InitQueue(Q); InQueue(Q, bt);
	f = r = 0;
	Qnum[r++]=1;
	while(!IsEmpty(Q)){
		OutQueue(Q, p); i=Qnum[f++];
		if(2*i > n || Data[2*i] == '#')
			p->lchild = NULL;
		else{
			p->lchild = (BiTree)malloc(sizeof(BTNode));
			p->lchild->data = Data[2*i];
			InQueue(Q, p->lchild);
			Qnum[r++] = 2*i;
		}
		if(2*i+1 > n || Data[2*i+1] == '#')
			p->rchild = NULL;
		else{
			p->rchild = (BiTree)malloc(sizeof(BTNode));
			p->rchild->data = Data[2*i+1];
			InQueue(Q, p->rchild);
			Qnum[r++] = 2*i+1;
		}
	}
}

void PreOrderTraverse(BiTree bt){
	if(bt){
		printf("%3c", bt->data);
		PreOrderTraverse(bt->lchild);
		PreOrderTraverse(bt->rchild);
	}
}

void InOrderTraverse(BiTree bt){
	if(bt){
		InOrderTraverse(bt->lchild);
		printf("%3c", bt->data);
		InOrderTraverse(bt->rchild);
	}
}

void PostOrderTraverse(BiTree bt){
	if(bt){
		PostOrderTraverse(bt->lchild);
		PostOrderTraverse(bt->rchild);
		printf("%3c", bt->data);
	}
}

struct Stack{
	BiTree *base;
	int top;
};

void Push(Stack &s, BiTree bt){
	s.base[++s.top] = bt;
}

int GetTop(Stack s, BiTree &bt){
	if(!s.top)
		return 0;
	bt = s.base[s.top];
	return 1;
}

int IsSEmpty(Stack s){
	return s.top==0? 1 : 0;
}

void InitStack(Stack &s){
	s.base = (BiTree *)malloc(MAX*(sizeof(BiTree)));
	s.top=0;
}

void Pop(Stack &s, BiTree &bt){
	if(IsSEmpty(s))
		return ;
	bt = s.base[s.top];
	s.top--;
}

void PreOrderTraverse2(BiTree bt){
	if(bt){
		Stack S;
		BiTree p;
		InitStack(S);
		Push(S, bt);
		while(!IsSEmpty(S)){
			while(GetTop(S, p) && p){
				printf("%3c", p->data);
				Push(S, p->lchild);
			}
			Pop(S, p);
			if(!IsSEmpty(S)){
				Pop(S, p);
				Push(S, p->rchild);
			}
		}
	}
} 

void InOrderTraverse2(BiTree bt){
	if(bt){
		Stack S;
		BiTree p;
		InitStack(S);
		Push(S, bt);
		while(!IsSEmpty(S)){
			while(GetTop(S, p) && p)
				Push(S, p->lchild);
			Pop(S, p);
			if(!IsSEmpty(S)){
				Pop(S, p);
				printf("%3c", p->data);
				Push(S, p->rchild);
			}
		}
	}
} 

void PostOrderTraverse2(BiTree bt){
	if(bt){
		Stack S;
		BiTree p, q;
		InitStack(S);
		Push(S, bt);
		while(!IsSEmpty(S)){
			while(GetTop(S, p) && p)
				Push(S, p->lchild);
			Pop(S, p);
			if(!IsSEmpty(S)){
				GetTop(S, p);
				if(p->rchild)
					Push(S, p->rchild);
				else{
					Pop(S, p);
					printf("%3c", p->data);
					while(!IsSEmpty(S) && GetTop(S, q) && q->rchild == p){
						Pop(S, p);
						printf("%3c", p->data);
					}
					if(!IsSEmpty(S)){
						GetTop(S, p);
						Push(S, p->rchild);
					}
				}
			}
		}
	}
}

void LevelOrderTraverse(BiTree bt){
	if(bt){
		Queue Q;
		BiTree p;
		InitQueue(Q);
		InQueue(Q, bt);
		while(!IsEmpty(Q)){
			OutQueue(Q, p);
			printf("%3c", p->data);
			if(p->lchild)
				InQueue(Q, p->lchild);
			if(p->rchild)
				InQueue(Q, p->rchild);
		}
	}
}

void CountLeaf(BiTree bt, int &leaves, int &cnt, char *lea){
	if(bt){
		cnt++;
		CountLeaf(bt->lchild, leaves, cnt, lea);
		if(!bt->lchild && !bt->rchild)
			lea[leaves++]=bt->data;
		CountLeaf(bt->rchild, leaves, cnt, lea);
	}
}

int main(){
	BiTree bt;
	char date[MAX];
	printf("請輸入一維陣列結構的二叉樹:\n");
	scanf("%s", date+1);
	int n=strlen(date+1);
	CreatBiTree(bt, date, n);
	printf("遞迴先序遍歷:"); 
	PreOrderTraverse(bt);
	printf("\n");
	printf("遞迴中序遍歷:");
	InOrderTraverse(bt);
	printf("\n");
	printf("遞迴後序遍歷:");
	PostOrderTraverse(bt);
	printf("\n\n");
	
	printf("非遞迴先序遍歷:"); 
	PreOrderTraverse2(bt);
	printf("\n");
	printf("非遞迴中序遍歷:");
	InOrderTraverse2(bt);
	printf("\n");
	printf("非遞迴後序遍歷:");
	PostOrderTraverse2(bt);
	printf("\n\n");
	
	printf("層次遍歷:");
	LevelOrderTraverse(bt);
	printf("\n\n"); 
	
	int cnt=0, sum=0;
	char leaves[MAX];
	CountLeaf(bt, sum, cnt, leaves);
	printf("葉子節點總數為:%d\n", sum);
	printf("分別是:");
	for(int i=0;i<sum;i++)
		printf("%3c", leaves[i]);
	printf("\n節點總數為:%d\n", cnt); 
	return 0;
}