CCCC-二叉搜索树

二叉搜索树就是左边的任何元素一定比根节点小,右边任何元素一定比根节点大或者等于根节点

10:二叉排序树

总时间限制:
1000ms
内存限制:
128000kB
描述

依次给出n(0<n<=100000)个整数,请你以这n个数创建一棵二叉排序树,这棵排序树的根节点为第一个数,并输出其中序遍历和后序遍历。

输入
共两行,第一行为整数n,第二行为n个整数
输出
共两行,第一行为中序遍历,第二行为后序遍历
样例输入
8
23 45 12 6 7 89 13 47
样例输出
6 7 12 13 23 45 47 89 
7 6 13 12 47 89 45 23
这道题就是一道搜索树的题目,对于这道题来说,第一个肯定是根节点的话,要注意,如果后面的顺序变了的话,建出来的树会不一定一样的。因为我们先取出第一个数,然后把比他小的按顺序放在left数组,比他大或者等于的放在right数组,这时候left,right的第一个元素就是23的儿子结点,相当于前序遍历一样,但又不完全是前序遍历。搜索树的最大特点就是他的中序遍历其实是一个升序,也就是说对原来数组sort一下就是中序遍历的结果了。后序遍历就直接用递归就好了

代码如下:

#include<cstdio>
#include<algorithm>
using namespace std;
int tree[100005];
int back[100005];
int back_num;
int left[100005],right[100005];
struct TREE
{
	int n;
	struct TREE *left;
	struct TREE *right;
};

void nomirror(int start,int end,struct TREE *p)
{
	int root=tree[start];
	int i,j,k,l;
	int flag1=start,flag2=end;
	p->n=root;
	
	if(end-start<=1)
	{
		p->left=p->right=NULL;
		return;
	}
	
	for(i=start+1,k=0,l=0;i<end;i++)
		if(tree[i]<tree[start])
			left[k++]=tree[i];
		else
			right[l++]=tree[i];
	for(i=start+1,j=0;j<k;i++)
	{
		tree[i]=left[j++];
	}
	for(j=0;j<l;i++)
	{
		tree[i]=right[j++];
	}
			
	for(i=start+1;i<end;i++)
	{
		if(tree[i]<root)
		{
			flag1=i;
			break;
		}
	}
	for(i=start+1;i<end;i++)
	{
		if(tree[i]>=root)
		{
			flag2=i;
			break;
		}
	}	
	if(flag1!=start)
	{
		p->left=(struct TREE*)malloc(sizeof(struct TREE));
		nomirror(flag1,flag2,p->left);
	}	
	else
		p->left=NULL;	
	if(flag2!=end)
	{
		p->right=(struct TREE*)malloc(sizeof(struct TREE));
		nomirror(flag2,end,p->right);
	}
	else
		p->right=NULL;
}

void back_erg(struct TREE *p)
{
	if(p->left!=NULL)
		back_erg(p->left);
	if(p->right!=NULL)
		back_erg(p->right);
	back[back_num++]=p->n;
}

int main()
{
	int n,i,j;

	struct TREE *r;
	scanf("%d",&n);
	for(i=0;i<n;i++)
		scanf("%d",&tree[i]);	
	r=(struct TREE*)malloc(sizeof(struct TREE));
	nomirror(0,n,r);
	sort(tree,tree+n);
	for(i=0;i<n-1;i++)
		printf("%d ",tree[i]);
	printf("%d\n",tree[i]);
	back_num=0;
	back_erg(r);
	for(i=0;i<n-1;i++)
		printf("%d ",back[i]);
	printf("%d\n",back[i]);
	return 0;
}

进阶一点的话,一个搜索树也可能被翻转过来,不过他还依然像个搜索树,他的中序遍历会变成降序。

L2-004. 这是二叉搜索树吗?

一棵二叉搜索树可被递归地定义为具有下列性质的二叉树:对于任一结点,

  • 其左子树中所有结点的键值小于该结点的键值;
  • 其右子树中所有结点的键值大于等于该结点的键值;
  • 其左右子树都是二叉搜索树。

所谓二叉搜索树的“镜像”,即将所有结点的左右子树对换位置后所得到的树。

给定一个整数键值序列,现请你编写程序,判断这是否是对一棵二叉搜索树或其镜像进行前序遍历的结果。

输入格式:

输入的第一行给出正整数N(<=1000)。随后一行给出N个整数键值,其间以空格分隔。

输出格式:

如果输入序列是对一棵二叉搜索树或其镜像进行前序遍历的结果,则首先在一行中输出“YES”,然后在下一行输出该树后序遍历的结果。数字间有1个空格,一行的首尾不得有多余空格。若答案是否,则输出“NO”。

输入样例1:
7
8 6 5 7 10 8 11
输出样例1:
YES
5 7 6 8 11 10 8
输入样例2:
7
8 10 11 8 6 7 5
输出样例2:
YES
11 8 10 7 5 6 8
输入样例3:
7
8 6 8 5 10 9 11
输出样例3:
NO

这道题目我的做法是先把他当成不是镜像来写,如果不符合,再去判断如果他是镜像行不行,两种都不行的话就只能是NO了。

代码如下:

#include<stdio.h>
#include<stdlib.h>
int sw,k;
int tree[1005],back[1005];

struct TREE
{
	int n;
	struct TREE *left;
	struct TREE *right;
};

void nomirror(int start,int end,struct TREE *p)
{
	int root=tree[start];
	int flag1=start,flag2=end,i;
	p->n=root;
	if(end-start<=1)
	{
		p->left=p->right=NULL;
		return;
	}
		
	for(i=start+1;i<end;i++)
	{
		if(tree[i]<root)
		{
			flag1=i;
			break;
		}
	}
	for(i=start+1;i<end;i++)
	{
		if(tree[i]>=root)
		{
			flag2=i;
			break;
		}
	}
	if(flag1>flag2)
	{
		sw=0;
		return;
	}
	for(i=flag2;i<end;i++)
		if(tree[i]<root)
		{
			sw=0;
			return;
		}	
	if(sw&&flag1!=start)
	{
		p->left=(struct TREE*)malloc(sizeof(struct TREE));
		nomirror(flag1,flag2,p->left);
	}	
	else
		p->left=NULL;	
	if(sw&&flag2!=end)
	{
		p->right=(struct TREE*)malloc(sizeof(struct TREE));
		nomirror(flag2,end,p->right);
	}
	else
		p->right=NULL;
}

void mirror(int start,int end,struct TREE *p)
{
	int root=tree[start];
	int flag1=start,flag2=end,i;
	p->n=root;
	if(end-start<=1)
	{
		p->left=p->right=NULL;
		return;
	}
	for(i=start+1;i<end;i++)
	{
		if(tree[i]>=root)
		{
			flag1=i;
			break;
		}
	}
	for(i=start+1;i<end;i++)
	{
		if(tree[i]<root)
		{
			flag2=i;
			break;
		}
	}
	if(flag1>flag2)
	{
		sw=0;
		return;
	}
	for(i=flag2;i<end;i++)
		if(tree[i]>=root)
		{
			sw=0;
			return;
		}	
	if(sw&&flag1!=start)
	{
		p->left=(struct TREE*)malloc(sizeof(struct TREE));
		mirror(flag1,flag2,p->left);
	}		
	else
		p->left=NULL;
	if(sw&&flag2!=end)
	{
		p->right=(struct TREE*)malloc(sizeof(struct TREE));
		mirror(flag2,end,p->right);
	}
	else
		p->right=NULL;
}

void back_erg(struct TREE *p)
{
	if(p->left!=NULL)
		back_erg(p->left);
	if(p->right!=NULL)
		back_erg(p->right);
	back[k++]=p->n;
}

int main()
{
	int n,i;
	struct TREE *r;
	scanf("%d",&n);
	for(i=0;i<n;i++)
		scanf("%d",&tree[i]);
	sw=1;
	r=(struct TREE*)malloc(sizeof(struct TREE));
	nomirror(0,n,r);
	if(sw)
	{
		printf("YES\n");
		k=0;
		back_erg(r);
		for(i=0;i<n-1;i++)
			printf("%d ",back[i]);
		printf("%d\n",back[i]);
	}
	else
	{
		sw=1;
		mirror(0,n,r);
		if(sw)
		{
			printf("YES\n");
			k=0;
			back_erg(r);
			for(i=0;i<n-1;i++)
				printf("%d ",back[i]);
			printf("%d\n",back[i]);			
		}
		else
			printf("NO\n");
	}
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值