数据结构与算法——03-树2 List Leaves(浙大陈姥姥《数据结构与算法》)

1. 题目描述

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.

Sample Input:

8
1 -
- -
0 -
2 7
- -
- -
5 -
4 6

Sample Output:

4 1 5

2. 题目理解

关键:除去第一行输入(第一行是后面的节点数目)。后面第M行输入,都表示一个节点,这个节点的val=M-1节点的左右子节点的val分别等于该行的两个输入;如果输入为‘-’,表示该子节点不存在。

第一行“1 -”,表示节点的val=0左子节点val=1,右子节点不存在;第二行“- -”,表示节点的val=1,该节点不存在左右子节点;最后一行“4 6”,表示该节点的val=7,该节点的左子节点的val=4右子节点的val=6.因此整个二叉树画出来如下图:

由于节点的输入是无序的,因此题目的关键是如何确定根节点,因为一旦确定了根节点,其他所有节点都可以通过树的遍历来获得重点:根节点不是任何节点的子节点!因此:在输入中出现过的数字(val)所表示的节点是某个节点的子节点,因此该节点不是根节点,所以只需要找输入中不曾出现的数字即可。

还是上图的输入,输入中出现了:0,1,2,4,5,6,7这7个数,二叉树总共有8个节点,因此根节点就是val为3的那个节点。

知道了怎么找到根节点,下面按照从上到下,从左到右的顺序输出叶子节点,其实就是数的层序遍历了,需要用到队列

3. 代码实现(C++)

#include <iostream>
#include <vector>
#include <queue>
using namespace std;
typedef struct TreeNode {//二叉树Node定义
	int val;
	int left;
	int right;
}Node;

int ReadInput(vector<Node>&nodeList);//循环读取输入数据
void ListLeaves(vector<Node>&nodeList, int rootIdx);//根据叶子节点索引rootIdx,层序遍历二叉树,打印叶子节点的val
int main(void) {
	int num;
	cin >> num;//读入数据行数n
	vector<Node> nodeList(num);//创建节点数组
	//循环读入输入节点数据,并找到根节点的位置
	int rootIdx = ReadInput(nodeList);
	//层序遍历,打印叶子节点
	ListLeaves(nodeList, rootIdx);

	return 0;
}
//循环读取输入数据
int ReadInput(vector<Node>&nodeList) {
	int num = nodeList.size();
	int val;
	vector<int> list(num, 1);
	char left, right;
	for (int i = 0; i < num; i++) {	//循环读入
		cin >> left >> right;
		nodeList[i].val = i;
		//判断当前节点的左右节点是否为空,如果为空,将子节点idx设为-1
		if (left!='-') {
			nodeList[i].left = left - '0';
			list[nodeList[i].left] = 0;
		}else nodeList[i].left = -1;

		if (right!='-') {
			nodeList[i].right = right - '0';
			list[nodeList[i].right] = 0;
		}else nodeList[i].right = -1;
	}
	for (int i = 0; i < num; i++) {
		if (list[i])return i;//i是根节点所在的位置
	}
}
//根据叶子节点索引rootIdx,层序遍历二叉树,打印叶子节点的val
void ListLeaves(vector<Node>&nodeList, int rootIdx) {
	queue<Node> nodeQueue;
	nodeQueue.push(nodeList[rootIdx]);//将根节点压入队列
	while (!nodeQueue.empty()) {//如果队列不为空,继续操作
		Node tmpNode = nodeQueue.front();
		nodeQueue.pop();//获得队列首元素
		if (tmpNode.left == -1 && tmpNode.right == -1) {//如果当前节点不存在子节点,打印当前节点val
			cout << tmpNode.val;
			if (!nodeQueue.empty())cout << " ";
		}
		//将当前节点的左右子节点入队
		if (tmpNode.left != -1)nodeQueue.push(nodeList[tmpNode.left]);
		if (tmpNode.right != -1)nodeQueue.push(nodeList[tmpNode.right]);

	}
}

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值