您的位置:首页 > 理论基础 > 数据结构算法

PAT 数据结构 03-树2 List Leaves

2020-06-24 04:26 399 查看

03-树2 List Leaves

Given a tree, you are supposed to list all the leaves in the order of top down, and left to right.

Input Specification:

Each input file contains one test case. For each case, the first line gives a positive integer N (≤10) which is the total number of nodes in the tree – and hence the nodes are numbered from 0 to N−1. Then N lines follow, each corresponds to a node, and gives the indices of the left and right children of the node. If the child does not exist, a “-” will be put at the position. Any pair of children are separated by a space.

Output Specification:

For each test case, print in one line all the leaves’ indices in the order of top down, and left to right. There must be exactly one space between any adjacent numbers, and no extra space at the end of the line.

题目有两个要点:

  1. 树的输入,也就是如何构建一棵树,用什么结构来存储。(这里采用数组的方式存储)
  2. 如何按照从上到下,从左到右的顺序输出叶子结点。(这个顺序其实也就是按层次遍历树)

先来解决第一个问题:树的存储

每个结点的结构:

typedef struct mytree{
int elem;
int left;
int right;
};

由于输入顺序并不是按照树的结构,从上到下,从左到右输入的,因此,为了能够实现层次遍历,必须找到树的根结点,最关键的地方在于如何寻找根节点

根结点的特征在于:输入的结点当中没有指向它的元素。因此可以知道,在所有输入的左右结点位置中,没有根结点所在的位置。 由此,也就是说要遍历所有输入的数字,找到从0~N-1中缺少的那个数字,其便是根结点。 因此,可以设置一个flag,来判断该数字有无输入。

int createTree(mytree t[]){
cin>>N;//N为全局变量
if(N==0)return -1;
int check[maxsize];
for(int i=0;i<N;i++)check[i]=0;//判断数字是否输入的flag
for(int i=0;i<N;i++){
char l,r;
cin>>l>>r;
if(l!='-'){	//当其有左孩子
t[i].left=l-'0';
check[t[i].left]=1;//左孩子的结点有输入,因此将其设为1
}
else t[i].left=-1;//无左孩子,则将其设为-1
if(r!='-'){//同左孩子
t[i].right=r-'0';
check[t[i].right]=1;
}
else t[i].right=-1;
}
int i=0;
for(;i<N;i++)
if(check[i]==0) break;//若check为0,则表明该结点(i)没有结点指向它
return i;//返回根结点

}

第二个问题:层次遍历

可能在数据结构的课上都曾经讲解过。需要使用队列作为辅助,当当前元素出队时,将其左右孩子分别入队,队列pop出的序列就是按层次遍历的序列。 当发现其没有左右孩子时,便记录下这个元素

void findLeaves(mytree t[],int root){
queue<int> q;
if(root==-1){ cout<<-1<<endl; return ;}//如果根为-1,表示是空树
int m=-1;//左孩子
int n=-1;//右孩子
int x[maxsize];//记录叶子结点
int j=0;//记录叶子结点数
q.push(root);//先把根结点入队
for(int i=0;i<N;i++){	//全局变量N,树的结点数
if(m!=-1) q.push(m);
if(n!=-1) q.push(n);  //如果有孩子,则入队
m=t[q.front()].left;  //下一个元素pop前,先记录下其左右孩子,下次入队
n=t[q.front()].right;
if(m==-1&&n==-1){x[j]=q.front();j++;}//如果都为空,说明为叶子结点
q.pop();
}
int i=0;
for(;i<j-1;i++){
cout<<x[i]<<' ';
}
cout<<x[i]<<endl;
return ;
}

mian函数:

int main(){                         //主函数
#ifdef ONLINE_JUDGE                 //如果有oj系统(在线判定),则忽略文件读入,否则使用文件作为标准输入
#else
freopen("1.txt", "r", stdin);   //从1.txt输入数据
#endif
mytree t1[maxsize];
int root=createTree(t1);
findLeaves(t1,root);

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: