2021-02-04

2021/2/4

把前几天的二叉树的题也记录一下
1.
在这里插入图片描述
在这里插入图片描述
这题中给出我们二叉树的一个层次序列让我们,输出这颗树的后序遍历,二叉树有4种遍历
前序遍历:父节点 左孩子 右孩子
中序遍历:左孩子 父节点 右孩子
后序遍历:左孩子 右孩子 父节点
前中后就指的是父节点(根节点的位置)
层次遍历:从根节点开始,一层一层,从左往右的遍历树。
这个题中,给出我们一个层次遍历,我们就可以根据这个层次序列构造一颗树,然后再输出他的后序遍历。用层次序列构造树的话,我们可以借用队列,从根节点开始,构造。
AC代码

#include<stdio.h>
#include<stdlib.h>
int i;
typedef struct tree
{
	struct tree *left;
	struct tree *right;
	int value;
}node;//建立一个树的结构体,包含左右子节点,和节点值
node *creat(int a[],int n)//层次的构造一颗树
{
	if(a[n]==-1)//层次序列以-1结束
	return NULL;
	node *t,*p;
	t=p=(node*)malloc(sizeof(node));
	node *dl[1100];//这个队列用于存放我们构造树的时候,左右子节点,然后一直走,这样就做到了层次构造
	int front,rear;
	front=rear=0;
	if(a[n]!=0)
	{
		t->value=a[n];
		t->left=NULL;
		t->right=NULL;//左右节点每次都要先为NULL
		dl[++rear]=t;
		n++;//根节点入队,n是其序列的下标
	}
	while(n<i)//当点取完了结束
	{
		p=dl[++front];//上一个节点出队
		//下面是构造出队的节点的左节点,右节点
		if(a[n]!=0&&n<i)//当为0的时候就代表无左节点
		{
			p->left=(node*)malloc(sizeof(node));
			p->left->left=p->left->right=NULL;//这里左节点的左节点和右节点要为空,这样结束的时候,不会出现叶节点左右节点不为空
			p->left->value=a[n];
			n++;
			dl[++rear]=p->left;//左节点入队
		}
		else {
		p->left=NULL;n++;}
		//下面为右节点的构造
		if(a[n]!=0&&n<i)
		{
			p->right=(node*)malloc(sizeof(node));
			p->right->left=p->right->right=NULL;
			p->right->value=a[n];
			n++;
			dl[++rear]=p->right;
		}
		else {
		p->right=NULL;n++;}
	}
	return t;//返回根节点
}
void houxu(node *t)
{
//后序遍历递归
	if(t==NULL)
		return;
	houxu(t->left);
	houxu(t->right);
	printf("%d ",t->value);
}
int ceng(node *t)
{
//计算层数
	if(t==NULL)
	return 0;
	int cengshu=1;//因为根节点也算一层,所以初值为1
	int x,y,z;
	x=ceng(t->left);//返回左节点的层数
	y=ceng(t->right);//返回右节点的层数
	z=x>y?x:y;//保存左右节点里面比较大的一个
	cengshu+=z;
	return cengshu;
}
int main()
{
	int t;
	scanf("%d",&t);
	while(t--)
	{
		i=1;
		int a[1100]={0};//用于保存层次序列
		int cengshu=0;
		node *T=(node*)malloc(sizeof(node));
		while(scanf("%d",&a[i]))
		{
			if(a[i]==-1) break;
			i++;	
		}		
		T=creat(a,1);
		cengshu=ceng(T);
		printf("%d ",cengshu);
		houxu(T);
		printf("\n");
	}	
} 

在这里插入图片描述
在这里插入图片描述
当知道中后序的特点后,可以通过2个序列构造出这颗树,然后先序输出,,不过我们可以在找的过程中直接输出,我们构造为3个步骤,第一步找出根节点并输出,它就在后序遍历的最后一个,第二步在中序遍历中找到根节点的位置,第三步,对左右节点进行相应的操作。
AC代码

#include<stdio.h>
#include<string.h>
void fun(int aleft,int aright,int bleft,int bright,char a[],char b[])
{
	if(aleft>aright||bleft>bright)//当左右节点某一个为空的时候,结束递归
	return ;
	printf("%c ",b[bright]);//输出父节点
	int i=aleft;
	while(a[i]!=b[bright])
	i++;//在中序中找到父节点的位置
	fun(aleft,i-2,bleft,i-aleft+bleft-2,a,b);//递归左序列
	fun(i+2,aright,i-aleft+bleft,bright-2,a,b);//递归右序列
}
int main()
{
	char a[1000],b[1000];
	gets(a);
	gets(b);
	int i,j;
	for(i=0;a[i]!='\0';i++);
	for(j=0;b[j]!='\0';j++);//i,j定位到最后一个字符的位置
	fun(0,i-1,0,j-1,a,b);	
}

在这里插入图片描述
在这里插入图片描述
这题要我们利用前序序列构造一颗二叉树,利用前序的性质,最前面那个就是我们的根节点,所以我们递归大概就是
1.建根节点
2.建左节点
3.建右节点
该题中用#号标识虚节点,所以我们递归左节点完了后,他的左右节点都会为虚,我们就结束,所递归结束条件就出来了,层序遍历的话,我们可以借助队列
AC代码

#include<stdio.h>
#include<stdlib.h>
char a[2004];
int i=1;
typedef struct tree
{
	struct tree *left;
	struct tree *right;
	char value;
}node;
node *zhaoshu()
{	
	node *t=(node*)malloc(sizeof(node));
	char ch=a[i++];//获取根节点
	if(ch!='\0')//序列结束跳出
	{
		if(ch!='#')//节点为虚,跳出
		{
			t->value=ch;
			t->left=zhaoshu();//递归左节点
			t->right=zhaoshu();//递归右节点
		}
		else return NULL;
	}
	return t;//返回根节点
}
void zhongxu(node *t)
{	
//中序输出	
	if(t==NULL)
		return;
	zhongxu(t->left);
	printf("%c",t->value);
	zhongxu(t->right);
}
void houxu(node *t)
{
//后序输出
		if(t==NULL)
		return;
	houxu(t->left);
	houxu(t->right);
	printf("%c",t->value);
}
void cengxu(node *t)
{
	if(t==NULL)
		return;
	node *duilie[1100];
	int front,rear;
	front=rear=0;
	duilie[++rear]=t;//根节点入队
	while(front!=rear)//空队退出
	{
		node *p=(node*)malloc(sizeof(node));
		p=duilie[++front];//出队
		printf("%c",p->value);//输出父节点
		if(p->left!=NULL) duilie[++rear]=p->left;//有左节点就递归输出左节点的
		if(p->right!=NULL) duilie[++rear]=p->right;//右节点
		
	}
}
int main()
{
	while(~scanf("%s",a+1))
	{
	node *T;
	i=1;
	T=zhaoshu();//先构造出树
	zhongxu(T);//中序输出
	printf(" ");
	houxu(T);//后序输出
	printf(" ");
	cengxu(T);//层序输出
	printf("\n");
	}
}

在这里插入图片描述
在这里插入图片描述
这题可以说结束上面那个题的分支
AC代码

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define maxsize 100
typedef struct tree
{
	char value;
	struct tree *left;
	struct tree *right;
}node;
typedef struct queue
{
	node *num[maxsize];
	int front;
	int rear;
}queue;
node *creat()
{
	char ch;
	node *a=(node*)malloc(sizeof(node));
	ch=getchar();
	if(ch!='\0')
	{
		if(ch!='#')
		{
			a->value=ch;
			a->left=creat();
			a->right=creat();
		}
		else return NULL;
	}
	else return a;
}
void shuchu(node *t)
{
	queue q;
	node *p;
	q.front=q.rear=0;
	q.num[++q.rear]=t;
	while(q.front!=q.rear)
	{
		p=q.num[++q.front];
		printf("%c",p->value);
		if(p->left!=NULL) q.num[++q.rear]=p->left;
		if(p->right!=NULL) q.num[++q.rear]=p->right;
	}
}
int main()
{
	node *T;
	T=creat();
	shuchu(T);
}

再来2个深搜
1.全排列

#include<stdio.h>
#include<string.h>
int n;
char a[15];//存储一开始需要排列的数 
char re[15];//存储每一次的排列 
int vis[15];//存储每一次的标记 
//假设有n个字符要排列,把他们以次放到n个箱子里面
//先要检查箱子是否为空,手中还有什么字符,把他们放进并标记
//放一次要恢复最初状态,当到n+1个箱子的时候一次全排列结束 
int check(int step)
{
	if(step==n+1)//满足条件 
		return 1;
	return 0;
}
void dfs(int step)//strp代表每次放的第几个箱子 
{	int i;
	if(check(step))//判断边界
	{	
		for(i=1;i<=n;i++)
		printf("%c",re[i]);//当step==n+1时代表一次排列完成,然后输出这个排列 
		printf("\n");
		return ;
	}	 
	for(i=1;i<=n;i++)//尝试每一种可能
	{
		 if(vis[i]==0)//满足check条件 
		{	re[step]=a[i];
			vis[i]=1;//标记 
	 		dfs(step+1);//继续下一步(step+1) 
		 	vis[i]=0;//变为最初状态(回溯的时候要用到) 
		} 
	}
	return ;
}

int main(void)
{
	int t;
	scanf("%d",&t);
	getchar();
	while(t--)
	{
		memset(a,0,sizeof(a));
		memset(vis,0,sizeof(a));//对存数据的数的数组进行初始化 
		scanf("%s",a+1);
		n=strlen(a+1);
		dfs(1);//从第一个箱子开始 
	}
	return 0;
} 
//深搜模板
check(int step)
{
	if()//看到没到树底
	return 1return 0} 
void dfs(int step)//step 代表走到了第几层树
{
	if()//使用check
	{
		//输出这次搜索的结果	
	} 
	//尝试这一层的每一个节点
	{
		//判断这个节点有没有被搜索过
		//如果没有那么保存在一个地方
		//进行就这个节点后的下一层搜索
		//当这个节点下面的分支搜索完了后,进行回溯,标记为没搜索过	
	} 
}
int main()
{
	//从第一层开始搜索	
}

2.组合数
这题主要是要考虑不取这个数的情况

#include<stdio.h>
#include<string.h>
int b[100000],a[1000000];//b存储组合数
int n,m;
void dfs(int step,int num)//step记录我们这次数要取出放在的位置,num表示当前取的数 
{
	if(step>m)
	{
		
		for(int i=1;i<=m;i++)
		printf("%d ",b[i]);
		printf("\n");
		return;//当step》m时表示已经去完了一次组合数 
	} 
	if(num<=n)
	{
	b[step]=num;
	dfs(step+1,num+1);//取这个数 
	dfs(step,num+1);//不取这个数 
	}
}
int main()
{
	while(scanf("%d %d",&n,&m)&&n!=0&&m!=0)
	{
		memset(b,0,sizeof(b));
		memset(a,0,sizeof(a));	
		dfs(1,1);
	}
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值