二叉树的遍历算法

二叉树的遍历算法

二叉树

链式存储

二叉链表
typedef struct BTNode{
	ElemType data;
	struct BTNode *lchild, *rchild;
} BTNode, *BinTree;
三叉链表
typedef struct BTNode{
	ElemType data;
	struct BTNode *lchild, *rchild, *parent;
} BTNode, *BinTree;

二叉链表和三叉链表都是用来描绘二叉树的!!

二叉树的遍历

一、层序遍历
void LevelOrder(BinTree bt){
	InitQueue(Q);//1.初始化队列
	EnQueue(bt);//2.根结点入队
	while(!QueueEmpty(Q)){//3.队列不为空
		DeQueue(Q, p);//4.出队
		if(p != NULL){//5.p结点不为空,则访问,并使孩子结点入队
			visit(p->data);
			EnQueue(p->lchild);
			EnQueue(p->rchild);
		}
	}
}
//#define MaxSize 1024
void LevelQueue(BinTree bt){
	const int MaxSize 1024;
	BinTree q[MaxSize];
	int front, rear;
	front = rear = 0;
	
	q[rear] = bt;
	rear = (rear + 1) % MaxSize;

	while(front != rear){
		p = q[front];
		front = (front + 1) % MaxSize;
		if(p != NULL){
			visit(p);
			q[rear] = p->lchild;
			rear = (rear + 1) % MaxSize;
			q[rear] = p->rchild;
			rear = (rear + 1) % MaxSize;
		}
	}
}
二、先序遍历

递归

void PreOrder(BinTree bt){
	if(bt != NULL){//递归中止条件
		visit(bt);
		PreOrder(bt->lchild);
		PreOrder(bt->rchild);
	}
}

非递归
因为栈是后进先出,所以最后进去的栈是二叉树最近的根结点,第一次进入左子树需要进栈,第二次访问右子树的时候,则需要出栈。无论是访问左子树还是右子树,都需要找到其双亲结点才能访问,因此栈只是用来记录双亲结点的顺序。

void PreOrder(BinTree bt, VisitFunc visit){
	InitStack(S);//1.初始化栈
	p = bt;//2.p指向根结点
	while(p != NULL || !StackEmpty(S)){//3.p不是空或者栈不空,则还有结点需要访问
		if(p != NULL){//4.p不是空,则需要访问p结点,并且说明其左子树还未访问,第一次进入需要入栈
			visit(p);
			Push(S, p);
			p = p->lchild;
		}else{//5.p是空,说明其双亲结点必定访问过,需要出栈,访问栈顶元素的右子树(栈里面元素的右子树必然没有访问过)。
			Pop(S, p);
			p = p->rchild;
		}
	}
}
void PreOrder(BinTree bt){
	InitStack(S);
	Push(S, bt);
	while(!StackEmpty(S)){
		Pop(S, p);
		if(p != NULL){
			visit(p);
			Push(S, p->rchild);//先进栈,后访问,所以右子树先进栈
			Push(S, p->lchild);
		}
	}
}
三、中序遍历

递归

void InOrder(BinTree bt){
	if(bt != NULL){
		InOrder(bt->lchild);
		visit(bt);
		InOrder(bt->rchild);
	}
}

非递归

void InOrder(BinTree bt){
	InitStack(S);//1.初始化栈
	BinNode *p = bt;//2.p指向根结点
	while(p != NULL || !StackEmpty(S)){//3.p不为空,或者栈不为空,则还有结点需要访问
		if(p){//4.p不为空,则第一次进过p,p进栈
			Push(S, p);
			p = p->lchild;
		}else{//5.p是空,则栈顶元素是第二次经过,需要访问了,并且访问右结点
			Pop(S, p);
			visit(p);
			p = p->rchild;
		}
	}
}
四、后续遍历

递归

void PostOrder(BinTree bt){
	if(bt != NULL){
		PostOrder(bt->lchild);
		PostOrder(bt->rchild);
		visit(bt);
	}
}

非递归

void PostOrder(BinTree T){
	InitStack(S);
	InitStack(tag);//1.
	p = T;//2.
	while(p != NULL || !StackEmpty(S)){//3.
		if(p != NULL){//4.
			Push(S, p);
			Push(tag, 1);
			p = p->lchild;
		}else{//5.
			Pop(S, p);
			Pop(tag, f);
			if(f == 1){//6.
				//从左子树返回,二次入栈,然后p转右子树
				Push(S, p);
				Push(tag, 2);
				p = p->rchild;
			}else{//7.
				//从右子树返回(二次出栈),访问根结点,p转上层
				visit(p);
				p = NULL;//必须要,使下一步继续退栈
			}
		}
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值