二叉树的遍历、计算、查找

#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;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值