浙江大学陈越教授数据结构PTA 题目——4-4 列出叶结点

一.题目理解

        1)叶(子)节点 终端结点 树叶:是度为 0 的结点。(带叶字或终端!)

              分支结点:度为0的结点。

                :结点、根节点

        2)层序遍历:从上到下、从左到右的顺序。(先进先出)

                a)借数组当队列!!

                b)层序遍历的结果存在数组ans[]中

                        法1:数组存储的是从根节点开始,左孩子,右孩子,左孩子的(左孩子,右孩子),右孩子的(左孩子,右孩子)…

                                1>找到根节点,存入数组ans[0]。

                                        找根节点way:利用输入为左右孩子序号,所以根节点会出现在输入中(因为根节点是任何结点的子节点)

                                2>利用for循环,从根节点开始,左孩子,右孩子,左孩子的(左孩子,右孩子),右孩子的(左孩子,右孩子)…

                                        注意:tree的下标是ans[i]
                                                  【理解:从根节点ans[0]开始的左孩子ans[1]、右孩子ans[2],然后左孩子ans[1]的(左孩子ans[3],右孩子ans[4])...】

int ans[15] = {};//借数组当队列,队列ans[i]是层序遍历的存储结果  
	for(int i = 0;i < n;i++)
	{
		if(checked[i] == 0)
		{
			ans[0] = i;	//找到根节点,存入数组ans[0]
			break;
		}
	}
	int k = 1;  //注意一下,k是从 1 开始的(因为根节点存进了ans[0]) 
	for(int i = 0;i < n;i++) //层序遍历存储:从根节点开始,左孩子,右孩子,左孩子的(左孩子,右孩子),右孩子的(左孩子,右孩子)… 
	{							
		if(tree[ans[i]].left != -1)ans[k++] = tree[ans[i]].left;	//tree的下标是ans[i]
																	//理解:从根节点ans[0]开始的左孩子ans[1]、右孩子ans[2],然后左孩子ans[1]的(左孩子ans[3],右孩子ans[4])...
		if(tree[ans[i]].right != -1)ans[k++] = tree[ans[i]].right;	
	}

                        法2:创建了一个二叉树,再层序输出(同数据结构书P115)

                                (有出队、左右孩子入队)

二.题目输入(是先中后序遍历)

        输入左右孩子序号的:使用结构体数组进行存储

                                                            【数组的下标就是数据域(即父节点),因此只需要保存每个结点的左右孩子】

 三.小知识点

        1)确定输入的是字符还是数字:定义为char型

        2)将char型的数字转化为int型数字:直接 减 ‘0’

               

                原因:

四.代码

法1:

#include <iostream>
#include <cstdio>
using namespace std;

struct Node
{
//	int data;	
	int left;
	int right;
};
int main()
{
	int n;
	cin >> n;
	getchar();  //千万千万注意这个getchar(),否则程序会直接崩溃
	Node tree[15];   //因为这个数组的下标就是data,所以我不需要额外的data域
	int checked[15] = {};   //检查根节点的(因为根节点不是任何结点的子节点,所以根节点不会出现在输入中) 
	for(int i = 0;i < n;i++)
	{
		char l,r;	
		scanf("%c %c",&l,&r);//输入用char 
		getchar();  
		if(l == '-')tree[i].left = -1;
		else
		{
			tree[i].left = (l - '0');
			checked[l - '0'] = 1;
		}
		if(r == '-')tree[i].right = -1;
		else
		{
			tree[i].right = (r - '0');
			checked[r - '0'] = 1;
		}
	}
	
	int ans[15] = {};//借数组当队列,队列ans[i]是层序遍历的存储结果  
	for(int i = 0;i < n;i++)
	{
		if(checked[i] == 0)
		{
			ans[0] = i;	//找到根节点,存入数组ans[0]
			break;
		}
	}
	int k = 1;  //注意一下,k是从 1 开始的(因为根节点存进了ans[0]) 
	for(int i = 0;i < n;i++) //层序遍历存储:从根节点开始,左孩子,右孩子,左孩子的(左孩子,右孩子),右孩子的(左孩子,右孩子)… 
	{							
		if(tree[ans[i]].left != -1)ans[k++] = tree[ans[i]].left;	//tree的下标是ans[i]
																	//理解:从根节点ans[0]开始的左孩子ans[1]、右孩子ans[2],然后左孩子ans[1]的(左孩子ans[3],右孩子ans[4])...
		if(tree[ans[i]].right != -1)ans[k++] = tree[ans[i]].right;	
	}
	
	
	int flag = 0;
	for(int i = 0;i < n;i++)
	{
		if(tree[ans[i]].left == -1 && tree[ans[i]].right == -1)//tree的下标是ans[i],因为ans[i]是层序遍历的存储结果 
		{
			if(flag)cout << " ";	
			flag = 1;
			cout << ans[i];
		}
	}
	return 0;
}

法2:

#include<stdio.h>
#include<stdlib.h>
typedef struct Node *node;
struct Node {//储存输入数据,并找到父节点
	int on;
    int left;
    int right;
};
typedef struct Snode *Tree;
struct Snode{//树
	int data;
	Tree Left;
	Tree Right;
};
int flag=1;//判断输出时第一个字母不带空格
Tree buidTree(int rot,node nod[]);
void myprint(Tree t);
int main(){
	int n,j=0,num[14]={0};
	node tr[14];
	char ch;
	scanf("%d",&n);
	scanf("%c",&ch);//清除回车
	char str[5];
	//输入数据,没有孩子的默认为1
	for(int i=0;i<n;i++){
		node t=(node)malloc(sizeof(struct Node));
		gets(str);
		if(str[0]!='-'){t->left=(int)(str[0]-'0');num[t->left]++;}
		else t->left=-1;
		if(str[2]!='-'){t->right=str[2]-'0';num[t->right]++;}
		else t->right=-1;
		t->on=i;//记住父节点值
		tr[i]=t;
	}
	//找根结点
	for(j;j<n;j++)
		if(num[j]==0)
			break;
	Tree T=buidTree(j,tr);
	myprint(T);
}

//层序输出
void myprint(Tree t){
	int first=0;
	Tree tep;
	Tree dd[12];
	int top=0,dom=0;//
	dd[top]=t;//借数组当队列用
	top++;
	while(dom<top){
		tep=dd[dom];//出队
		dom++;
		if(!tep->Left&&!tep->Right){
			first++;
			if(first==flag)printf("%d",tep->data);
			else printf(" %d",tep->data);
		}
		if(tep->Left){ dd[top]=tep->Left;top++;}//左右孩子入队
		if(tep->Right) {dd[top]=tep->Right;top++;}
	}
}
Tree buidTree(int rot,node nod[]){
	node t= nod[rot];
	Tree tr=(Tree)malloc(sizeof(struct Snode));
	tr->data=t->on;
	if(t->left!=-1){
		tr->Left=buidTree(t->left,nod);
	}else tr->Left=NULL;
	if(t->right!=-1){
		tr->Right=buidTree(t->right,nod);
	}else tr->Right=NULL;
	return tr;
}

        

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小吴同学·

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值