二叉树的遍历(包含非递归遍历)第三次总结

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

学这些简单的知识点人就麻了。。。


一、二叉树的基本操作(数据的类型不要太乱了,不然容易混淆,血与泪的教训)

1. 二叉树的初始化

typedef struct bitnode{
	elemtype data;
	struct bitnode *lchild, *rchild;//只有两个度;
}bitnode,*bitree;

2.创建一个二叉树

void createbitree(bitree *t)
{
    char c;
    scanf("%c",&c);
    if(c == '.')//.和#都可以
    {
        *t = NULL;
    }
    else
    {
        *t = (bitree)malloc(sizeof(bitnode));
        (*t)->data = c;
        createbitree(&(*t)->lchild);
        createbitree(&(*t)->rchild);
    }
}

3.二叉树的输出

void visit(bitree c)//
{
    printf("%c",c->data);
}

4.前序遍历(只需要记住遍历是 根左右 就可以了)

void preorder(bitree t){//先序遍历;根左右 
	if(t)
	{
		visit(t);
		preorder(t->lchild);
		preorder(t->rchild);
	}
}

5.中序遍历( 左根右 )

void inorder(bitree t){//中序遍历;左根右 
	if(t)
	{
		postorder(t->lchild);
		visit(t);
		postorder(t->rchild);
	}
}

6.后序遍历(左右根)这三个遍历用递归的话基本上大同小异,相较非递归而言并不是我们的重点

void postorder(bitree t){//后序遍历;左右根 
	if(t)
	{
		postorder(t->lchild);
		postorder(t->rchild);
		visit(t);
	}
}

7.前序遍历(非递归)

1.我们普通的搜索只能一直向一个方向(左或右)而栈可以保存上一个数据,从而可以回到上一个位置继续查找,进而查找另一边数 2.为什么push和pop不是一个类型的函数,我用void定义pop的时候,发现p=s->[s.top]这一步已经赋值了,但函数执行完毕的时候,p的指针就找不到位置了,为空,所以,我用了另一种方式,p的指针就不会突然找不到位置了。

void preorder2(bitree t){//先序非递归遍历(迭代法) 
	sqstack s;
	initstack(s);	
	bitree p =t;
	bitree a;	
	while(p || !stackempty(s)){	
		if(p)
		{
			visit(p);
			push(s,p);	
			p = p->lchild;
		}
		else
		{ 
			a=pop(s,p);
			p=a;
			p = p->rchild;	
		}
	}
}

8.中序遍历(非递归)和前序遍历差不多

void inorder2(bitree t){//中序非递归遍历(迭代法) 
	sqstack s;
	initstack(s);	
	bitree p =t;
	bitree a;	
	while(p || !stackempty(s))
	{	
		if(p)
		{
			push(s,p);	
			p = p->lchild;
		}
		else
		{ 
			a=pop(s,p);
			p=a;
			visit(p); 
			p = p->rchild;	
		}
	}
}

8.后序遍历(非递归)

这里也是一样,出栈赋值给q之后,q的指针就找不到方向了;

void postorder2(bitree t){//后序非递归遍历(迭代法) 
	sqstack s;
	initstack(s);
	bitree p = t;
	bitree a;
	bitree e;
	bitree r=NULL;	
	while(p || !stackempty(s)){	
		if(p)
		{
			push(s,p);	
			p = p->lchild;
		}
		else
		{
			e=checktop(p,s);
			p=e;
			if(p->rchild && p->rchild!=r)/*后序遍历需要去先查找右子树,
											所以将右子树的入栈,就有了这一步,
											这里需要注意的是,因为不让指针指
											向左子树的话,回到第一个push就会
											导致重复入栈*/
			{
				p=p->rchild;
				push(s,p);
				p=p->lchild;
			}
			else
			{
				a=pop(s,p);
				p=a;
				visit(p);
				r=p;/*将右子树的位置标记,就是在右边时*/
				p=NULL;	
			}
		}
	}
}

8.层次遍历(非递归)需要用到队列(利用它的先进先出的原则实行层次遍历)

void levelorder(bitree t){//层次遍历 
	sqqueue q;
	initqueue(q);
	bitree p=t;
	bitree a;
	enqueue(q,p);
	while(q.rear!=q.front)
	{
		a=dequeue(q,p);
		p=a;
		visit(p);
		if(p->lchild) enqueue(q,p->lchild);
		if(p->rchild) enqueue(q,p->rchild);
	}
} 

二、完整的代码

//输入为:AB.D…CE.F…
//12.46…3.5…
//ABC…DE…F.G…
这是三种数据输入,可以去试试哦

# include<stdio.h>
# include<stdlib.h>
# define maxsize 50
# define ok 1
# define error 0

typedef char elemtype;
typedef int status;
int cnt=0;
typedef struct bitnode{
	elemtype data;
	struct bitnode *lchild, *rchild;
}bitnode,*bitree;

typedef struct{
	bitree data[maxsize];
	int top;
	int length;
	int bottom;
}sqstack,*sqstackpoint;

typedef struct{
	bitree data[maxsize];
	int front,rear;
}sqqueue;
void createbitree(bitree *t)
{
    char c;
    scanf("%c",&c);
    if(c == '.')
    {
        *t = NULL;
    }
    else
    {
        *t = (bitree)malloc(sizeof(bitnode));
        (*t)->data = c;
        createbitree(&(*t)->lchild);
        createbitree(&(*t)->rchild);
    }
}

void initstack(sqstack &s){
	s.top=s.bottom=-1;
} 

bool stackempty(sqstack &s){
	if(s.top==-1) return ok;
	else return error;
}

void visit(bitree c)
{
    printf("%c",c->data);
}

void push(sqstack &s,bitree e){
	if(s.top==maxsize-1) return;
	else
	{
		s.top++;
		s.data[s.top]=e;
	}
}

bitree pop(sqstack &s,bitree e){
	if(s.top==-1) return error;
	else
	{
		e=s.data[s.top];
		s.top--;
		return e;
	}
}

bitree checktop(bitree q,sqstack &s){
	if(s.top==-1) return error;
	q=s.data[s.top]; 
	return q;
}

void initqueue(sqqueue &q){
	q.front=q.rear=-1;
}

bool queueempty(sqqueue &q){
	if(q.front==q.rear) return ok;
	else return error;
}
void enqueue(sqqueue &q,bitree e){
	if((q.rear+1)%maxsize==q.front) return;
	if(q.rear==maxsize) q.rear=q.rear%maxsize;
	q.rear++;
	q.data[q.rear]=e;
}

bitree dequeue(sqqueue &q,bitree e){
	if(q.rear==q.front) return error;
	if(q.front==maxsize) q.front=q.front%maxsize;
	q.front++;
	e=q.data[q.front]; 
	return e;
}

void inorder(bitree t){//中序遍历;左右根 
	if(t)
	{
		inorder(t->lchild);
		visit(t);
		inorder(t->rchild);
	}
}
void preorder(bitree t){//先序遍历;根左右 
	if(t)
	{
		visit(t);
		preorder(t->lchild);
		preorder(t->rchild);
	}
}


void postorder(bitree t){//后序遍历;左右根 
	if(t)
	{
		postorder(t->lchild);
		postorder(t->rchild);
		visit(t);
	}
}

void inorder2(bitree t){//中序非递归遍历(迭代法) 
	sqstack s;
	initstack(s);	
	bitree p =t;
	bitree a;	
	while(p || !stackempty(s))
	{	
		if(p)
		{
			push(s,p);	
			p = p->lchild;
		}
		else
		{ 
			a=pop(s,p);
			p=a;
			visit(p); 
			p = p->rchild;	
		}
	}
}
void preorder2(bitree t){//先序非递归遍历(迭代法) 
	sqstack s;
	initstack(s);	
	bitree p =t;
	bitree a;	
	while(p || !stackempty(s)){	
		if(p)
		{
			visit(p);
			push(s,p);	
			p = p->lchild;
		}
		else
		{ 
			a=pop(s,p);
			p=a;
			p = p->rchild;	
		}
	}
}
void postorder2(bitree t){//后序非递归遍历(迭代法) 
	sqstack s;
	initstack(s);
	bitree p = t;
	bitree a;
	bitree e;
	bitree r=NULL;	
	while(p || !stackempty(s)){	
		if(p)
		{
			push(s,p);	
			p = p->lchild;
		}
		else
		{
			e=checktop(p,s);
			p=e;
			if(p->rchild && p->rchild!=r)
			{
				p=p->rchild;
				push(s,p);
				p=p->lchild;
			}
			else
			{
				a=pop(s,p);
				p=a;
				visit(p);
				r=p;
				p=NULL;	
			}
		}
	}
}

void levelorder(bitree t){//层次遍历 
	sqqueue q;
	initqueue(q);
	bitree p=t;
	bitree a;
	enqueue(q,p);
	while(q.rear!=q.front){
		a=dequeue(q,p);
		p=a;
		visit(p);
		if(p->lchild) enqueue(q,p->lchild);
		if(p->rchild) enqueue(q,p->rchild);
	}
} 
//输入为:AB.D..CE.F...
//12.46...3.5..
//ABC..DE...F.G..
int main()
{
	
	bitree t;
	createbitree(&t);
	printf("递归遍历:\n");
	preorder(t);
	printf("\n");
	inorder(t);
	printf("\n");
	postorder(t); 
	printf("\n");
	printf("非递归遍历:\n");
	preorder2(t);
	printf("\n");
	inorder2(t);
	printf("\n");
	postorder2(t);
	printf("\n");
	levelorder(t);
	return 0;
} 

总结

再见!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值