树和二叉树:二叉树遍历的应用

树和二叉树:二叉树遍历的应用

二叉树3种递归遍历算法的应用

在这里插入图片描述
例题:假设二叉树采用二叉链存储结构存储,设计一个算法,计算一棵给定二叉树的所有节点个数
在这里插入图片描述
解:计算一棵二叉树b中所有节点个数的递归模型f(b)如下:
在这里插入图片描述
对应的递归算法如下:

int Nodes(BTNode *b) {
	int num1,num2;
	if(b==NULL)
		return 0;
	else
		return Node(b->lchild)+Node(b->rchild)+1;
} //先左子树,再右子树,最后根节点(计1)是后序遍历的思路

注:本例算法可以基于任何一种遍历算法

例题:假设二叉树采用二叉链存储结构存储,设计一个算法,计算一棵给定二叉树的所有叶子节点个数
在这里插入图片描述
解:计算一棵二叉树b中所有叶子节点个数的递归模型f(b)如下:
在这里插入图片描述
对应的递归算法如下:

int LeafNodes(BTNode *b) {
	int num1,num2;
	if(b==NULL)
		return 0;
	else if(b->lchild==NULL && b->rchild==NULL)
		return 1;
	else {
		num1=LeafNodes(b->lchild);
		num2=LeafNodes(b->rchild);
		return (num1+num2);
	}
}  //先左子树,再右子树,最后根节点(计0),是后序遍历的思路

注:同样本例算法可以基于任何一种遍历算法

例题:假设二叉树采用二叉链存储结构,设计一个算法把二叉树b复制到二叉树t中
在这里插入图片描述
对应的递归算法如下:

void Copy(BTNode *b,BTNode *&t) {
	if(b==NULL) 
		t=NULL;
	else {
		t=(BTNode *)malloc(sizeof(BTNode));
		t->data=b->data; //复制一个根节点*t
		Copy(b->lchild,t->lchild); //递归复制左子树
		Copy(b->rchild,t->rchild); //递归复制右子树
	}
} //先根节点,再左子树,最后右子树,是先序遍历的思路

例题:设二叉树采用二叉链存储结构,设计一个算法把二叉树b的左,右子树进行交换。要求不破坏原二叉树

解:本题要求不破坏原有二叉树,实际上就是建立一个新的二叉树t,它交换了二叉树b的左,右子树。其递归模型如下:
在这里插入图片描述
对应的递归算法如下:
在这里插入图片描述
例题:假设二叉树采用二叉链存储结构,设计一个算法Level()求二叉树b中值为x的节点的层次(假设所有节点值唯一)

Level(b,x,h) 返回二叉树b中data值为x的节点的层次,其中h表示b所指节点的层数

当在二叉树b中找到data值为x的节点,返回其层次(一个大于0的整数);若没有找到,返回0

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
对应的递归算法如下:

int Level(BTNode *b,ElemType x,int h) { //找到*p节点后h为其层次,否则为0
	if(b==NULL)
		return 0; //空树时返回0
	else if(b->data==x)
		return h; //找到节点时
	else {
		l=Level(b->lchild,x,h+1); //在左子树中查找
		if(l==0) //左子树中未找到时在右子树中查找
			return Level(b->rchild,x,h+1);
		else
			return l;
	}
}

注:基于先序遍历算法思想

层次遍历算法的应用

例题:假设二叉树采用二叉链存储结构,设计一个算法输出从根节点到每个叶子节点的逆路径
在这里插入图片描述
解:设计的队列为非环形队列qu,将所有已访问的节点指针进队,并在队列中保存双亲节点的位置

struct snode {
	BTNode *node; //存放当前节点指针
	int parent; //存放双亲节点在队列中的位置
}qu[MaxSize]; //定义非环形队列
int front=rear=-1; //置队列为空队列

当找到一个叶子节点时,在队列中通过双亲节点的位置输出根节点到该叶子节点的逆路径

注:类似于用队列求解迷宫问题

对应算法如下:

void AllPath(BTNode *b) {
	struct snode {
		BTNode *node; //存放当前节点指针
		int parent; //存放双亲节点在队列中的位置 
	}qu[MaxSize]; //定义非环形队列
	BTNode *q;
	int front,rear,p; //定义队头和队尾指针
	front=rear=-1; //置队列为空队列
	rear++;
	qu[rear].node=b; //根节点指针进入队列
	qu[rear].parent=-1; //根节点没有双亲节点
	while(front!=rear) { //队列不为空
		front++; //front是当前节点*q在qu中的位置
		q=qu[front].node; //队头出队列,该节点指针仍在qu中
		if(q->lchild==NULL && q->rchild==NULL) { //*q为叶子节点
			p=front; //输出*q到根节点的逆路径序列
			while(qu[p].parent!=-1) {
				printf("%c->",qu[p].node->data);
				p=qu[p].parent;
			}
			printf("%c\n",qu[p].node->data); 
		}
		if(q->lchild!=NULL) { //*q节点有左孩子时将其进列
			rear++;
			qu[rear].node=q->lchild;
			qu[rear].parent=front; //*q的左孩子的双亲位置为front 
		} 
		if(q->rchild!=NULL) { //*q节点有右孩子时将其进列
			rear++;
			qu[rear].node=q->rchild;
			qu[rear].parent=front; //*q的右孩子的双亲位置为front 
		}
	} 
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值