#include <stdio.h>
#define STACKSIZE 100
#define QUEUESIZE 100
//定义树的结构
//typedef tree* pTree;
typedef struct Tree{
char data;
struct Tree *lchild,*rchild;
int visited;
}Tree,*pTree;
//用前序遍历数组生成树
int i = 0;
void preOrderBuild(pTree *t,char preStr[]){
char ch = preStr[i++];
if (ch == '#')
*t = NULL;
else{
*t = (pTree)malloc(sizeof(Tree));
(*t)->data = ch;
(*t)->visited = 0;
preOrderBuild(&(*t)->lchild,preStr);
preOrderBuild(&(*t)->rchild,preStr);
}
}
//用中序遍历数组生成树
void inOrderBuild(pTree *t,char preStr[]){
char ch = preStr[i++];
if (ch == '#')
*t = NULL;
else{
*t = (pTree)malloc(sizeof(Tree));
preOrderBuild(&(*t)->lchild,preStr);
(*t)->data = ch;
(*t)->visited = 0;
preOrderBuild(&(*t)->rchild,preStr);
}
}
//前序遍历(递归)
void preOrderPrint(pTree t){
if (!t){
printf("# ");
return;
}
printf("%c ",t->data);
preOrderPrint(t->lchild);
preOrderPrint(t->rchild);
}
//中序遍历(递归)
void inOrderPrint(pTree t){
if (!t){
printf("# ");
return;
}
inOrderPrint(t->lchild);
printf("%c ",t->data);
inOrderPrint(t->rchild);
}
//后序遍历(递归)
void postOrderPrint(pTree t){
if (!t){
printf("# ");
return;
}
postOrderPrint(t->lchild);
postOrderPrint(t->rchild);
printf("%c ",t->data);
}
//定义栈和其操作
typedef struct Stack{
int top;
pTree data[STACKSIZE];
}Stack,*pStack;
void init_stack(Stack *s){
s->top = -1;
}
void push_stack(Stack *s,pTree e){
if(s->top == STACKSIZE)
printf("stack is full");
s->data[++s->top] = e;
}
pTree pop_stack(Stack *s){
if(s->top == -1)
return NULL;
return s->data[s->top--];
}
void test_stack(){
pTree t1;
pTree t2;
pTree t;
t1 = (pTree)malloc(sizeof(Tree));
t1->data = 'a';
t2 = (pTree)malloc(sizeof(Tree));
t2->data = 'b';
Stack stack;
init_stack(&stack);
push_stack(&stack,t1);
push_stack(&stack,t2);
t = pop_stack(&stack);
if (t)
printf("%c\n",t->data);
else
printf("null\n");
t = pop_stack(&stack);
if (t)
printf("%c\n",t->data);
else
printf("null\n");
t = pop_stack(&stack);
if (t)
printf("%c\n",t->data);
else
printf("null\n");
}
//前序遍历(非递归) 若树不为空,则输出数据,将右子树压入栈,赋值为左子树,否则出栈。此方法不便改为中序,不推荐
void preOrderPrint2(pTree t){
Stack stack;
init_stack(&stack);
while(t || ((stack.top) != -1)){
if(t){
printf("%c ",t->data);
push_stack(&stack,t->rchild);
t = t->lchild;
}
else{
printf("# ");
t = pop_stack(&stack);
}
}
printf("# ");
}
//前序遍历(非递归)2 若树不为空,则将树压入栈,赋值为左子树,否则出栈,输出数据,赋值为右子树。此方法方便改为中序后序,推荐
void preOrderPrint22(pTree t){
Stack stack;
init_stack(&stack);
while(t || ((stack.top) != -1)){
if(t){
printf("%c ",t->data);
push_stack(&stack,t);
t = t->lchild;
}
else{
printf("# ");
t = pop_stack(&stack);
t = t->rchild;
}
}
printf("# ");
}
//中序遍历(非递归)
void inOrderPrint2(pTree t){
Stack stack;
init_stack(&stack);
while(t || ((stack.top) != -1)){
if(t){
push_stack(&stack,t);
t = t->lchild;
}
else{
printf("# ");
t = pop_stack(&stack);
printf("%c ",t->data);
t = t->rchild;
}
}
printf("# ");
}
//后序遍历(非递归) 在树节点上加一个计数器,若左右子节点都访问过后再输出
void postOrderPrint2(pTree t){
Stack stack;
init_stack(&stack);
while(t || ((stack.top) != -1)){
if(t){
if(t->visited == 2){
printf("%c ",t->data);
t = pop_stack(&stack);
continue;
}
else if(t->visited == 0){
push_stack(&stack,t);
t->visited++;
t = t->lchild;
}
else{
push_stack(&stack,t);
t->visited++;
t = t->rchild;
}
}
else{
printf("# ");
t = pop_stack(&stack);
}
}
}
//定义队列和相关操作
typedef struct Queue{
int top;
int tail;
pTree data[QUEUESIZE];
}Queue,*pQueue;
void init_queue(pQueue p){
p->top = 0;
p->tail = 0;
}
void push_queue(pQueue p,pTree e){
p->data[p->top++] = e;
}
pTree pop_queue(pQueue p){
return p->data[p->tail++];
}
//层次遍历,由于先遍历的节点也先输出它的子节点,所以使用队列实现
void levelOrderPrint(pTree t){
pQueue p;
p = (pQueue)malloc(sizeof(Queue));
init_queue(p);
while(t || (p->top-p->tail > 0)){
if(t){
printf("%c ",t->data);
push_queue(p,t->lchild);
push_queue(p,t->rchild);
}
else{
printf("# ");
}
t = pop_queue(p);
}
printf("# ");
}
/*
A
B F
C D # G
# # E # # #
# #
*/
//查找结点
int find(pTree t,char key){
/*
if(!t)
return 0;
if(t->data == key)
return 1;
else{
if(find(t->lchild,key))
return 1;
else if(find(t->rchild,key))
return 1;
else
return 0;
}
*/
if(!t || (t->data != key && !find(t->lchild,key) && !find(t->rchild,key)))
return 0;
return 1;
}
//统计节点个数
int count(pTree t){
if(t)
return count(t->lchild)+count(t->rchild)+1;
else
return 0;
}
//比较两个树是否是同一个树
//计算树的深度
int getDepth(pTree t){
if(t){
int l,r;
l = getDepth(t->lchild);
r = getDepth(t->rchild);
return l > r ? l+1 : r+1;
}
else
return 0;
}
int main(){
pTree preTree;
char str[] = "ABC##DE###F#G##";
/*
A
B F
C D # G
# # E # # #
# #
*/
//先序建树
preOrderBuild(&preTree,str);
//递归实现三序遍历
preOrderPrint(preTree);printf("\n");
inOrderPrint(preTree);printf("\n");
postOrderPrint(preTree);printf("\n");
//非递归实现三序遍历
//preOrderPrint2(preTree);printf("\n");
//preOrderPrint22(preTree);printf("\n");
//inOrderPrint2(preTree);printf("\n");
//postOrderPrint2(preTree);printf("\n");
//层次遍历
//levelOrderPrint(preTree);printf("\n");
//计算节点个数
printf("%d\n",count(preTree));
//计算树的深度
printf("%d\n",getDepth(preTree));
printf("%d\n",find(preTree,'D'));
return 0;
}
二叉树的遍历、计算、查找
最新推荐文章于 2023-10-26 23:23:57 发布