中国大学MOOC-数据结构基础习题集、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.
Sample Input:
8 1 - - - 0 - 2 7 - - - - 5 - 4 6
Sample Output:
4 1 5
简单分析一下:
输入的第一行,是一个整数n,是节点的个数(≤10)。接下来是n行,每一行有两个数a和b,用来说明左孩子和有孩子是第几个节点。如果为空用‘-’表示。如第1行(准确说第0行)的a、b值分别是1和-,就是说标号为0的节点左孩子是标号为1的节点,右孩子为空。
输出的一行,是所有的叶子节点,要求从上到下,从左到右输出。
这道题应该分为两大步,第一步是建树,第二步是层次遍历。有的同学(比如我),发现了左右孩子都为‘-’为叶子节点,直接输出不就可以了?其实不是这样的,如果那样输出的顺序不对。因为题中要求了必须从上到下,从左到右输出。
先说说我的解题思路吧:
1. 首先定义两个结构体,一个是BinTreeNode(用于表示二叉树节点),一个是myNode(用于接收输入的数据)。template <class T>是模板,T是类型。使用方式如下:BinTreeNode<int> *root;。如果把模板去掉,T换成int,也可以,形如:BinTreeNode *root;。
1 template <class T> 2 struct BinTreeNode 3 { 4 BinTreeNode<T> *left; 5 BinTreeNode<T> *right; 6 T data; 7 BinTreeNode(T d, BinTreeNode<T> *l, BinTreeNode<T> *r) 8 { 9 data = d; 10 left = l; 11 right = r; 12 } 13 }; 14 15 typedef struct myNode 16 { 17 int left; 18 int right; 19 myNode(int l, int r): 20 left(l), right(r) 21 { 22 23 } 24 }myNode;
2. 接下来是输入。这里我们仍然用的是vector,之前看过其他几篇博客的人知道,博主是十分喜欢vector的,主要原因是其他的还不太会用……。
1 int main() 2 { 3 // 用到的数据结构 4 vector<myNode> vec; 5 vector<BinTreeNode<int> > res; 6 // 先输入一个整数 7 int n; 8 cin >> n; 9 // 再输入n行数据 10 char a, b; 11 for(int i=0; i<n; i++) 12 { 13 cin >> a >> b ; 14 vec.push_back(myNode(a, b)); 15 } 16 // ...
3. 下面开始建树了,首先要生成n个节点,接下来通过输入的信息把指针域“拼接”起来。
1 // 生成树的n个结点,放进vector里 2 for(int i=0; i<n; i++) 3 { 4 res.push_back(BinTreeNode<int>(i, NULL, NULL)); 5 } 6 // 建树 7 for(int i=0; i<n; i++) 8 { 9 if(vec[i].left != '-') 10 { 11 res[i].left = &res[vec[i].left - '0']; 12 } 13 else 14 { 15 res[i].left = NULL; 16 } 17 if(vec[i].right != '-') 18 { 19 res[i].right = &res[vec[i].right - '0']; 20 } 21 else 22 { 23 res[i].right = NULL; 24 } 25 }
4. 在这一步骤,我们需要找到树的根在哪。我的方法是:建一个大小为n的bool数组flag,初值为均为0。如果出现在输入里的节点,肯定不是根节点,对应的flag变为1。剩下来那一个为0的肯定就是根节点了。
1 // bool型数组帮助找到根节点 2 vector<bool> flag; 3 // 树的根节点 4 BinTreeNode<int> * root = NULL; 5 // 找到根节点,flag仍然为0的那个就是,当然这里还没有给head赋值 6 for(int i=0; i<n; i++) 7 { 8 flag.push_back(0); 9 } 10 for(int i=0; i<n; i++) 11 { 12 if(vec[i].left != '-') 13 flag[vec[i].left-'0'] = 1; 14 if(vec[i].right!= '-') 15 flag[vec[i].right-'0'] = 1; 16 } 17 18 for(int i=0; i<n; i++) 19 { 20 if(flag[i] == 0) 21 { 22 root = &res[i]; 23 break; 24 } 25 }
5. 借助队列进行层次遍历:首先根节点入队,然后循环进行如下步骤:出队、出队的节点的左右孩子依次入队(如果存在的话)、如果出队的节点是叶子节点(即左右孩子均为空)则把这个节点的data域放进名为result的vecotr里。
1 BinTreeNode<int> * p; 2 vector<int> result; 3 queue<BinTreeNode<int> *> que; 4 que.push(root); 5 6 while(p != NULL) 7 { 8 if(que.size() == 0) 9 break; 10 p = que.front(); 11 if(p -> left == NULL && p -> right == NULL) 12 { 13 result.push_back(p->data); 14 } 15 que.pop(); 16 if(p -> left != NULL) 17 { 18 que.push(p -> left); 19 } 20 if(p -> right != NULL) 21 { 22 que.push(p -> right); 23 } 24 }
6. 输出结果,最后一个空格不要有哦!
1 int len = result.size(); 2 for(int i=0; i<len ; i++) 3 { 4 cout << result[i]; 5 if(i != len - 1) 6 cout << " "; 7 } 8 return 0; 9 }
7. 完整的代码:
1 #include <iostream> 2 #include <vector> 3 #include <queue> 4 using namespace std; 5 6 template <class T> 7 struct BinTreeNode 8 { 9 BinTreeNode<T> *left; 10 BinTreeNode<T> *right; 11 T data; 12 BinTreeNode(T d, BinTreeNode<T> *l, BinTreeNode<T> *r) 13 { 14 data = d; 15 left = l; 16 right = r; 17 } 18 }; 19 20 typedef struct myNode 21 { 22 int left; 23 int right; 24 myNode(int l, int r): 25 left(l), right(r) 26 { 27 28 } 29 } myNode; 30 31 int main() 32 { 33 // 用到的数据结构 34 vector<myNode> vec; 35 vector<BinTreeNode<int> > res; 36 // 先输入一个整数 37 int n; 38 cin >> n; 39 // 再输入n行数据 40 char a, b; 41 for(int i=0; i<n; i++) 42 { 43 cin >> a >> b ; 44 vec.push_back(myNode(a, b)); 45 } 46 // 生成树的n个结点,放进vector里 47 for(int i=0; i<n; i++) 48 { 49 res.push_back(BinTreeNode<int>(i, NULL, NULL)); 50 } 51 // 建树 52 for(int i=0; i<n; i++) 53 { 54 if(vec[i].left != '-') 55 { 56 res[i].left = &res[vec[i].left - '0']; 57 } 58 else 59 { 60 res[i].left = NULL; 61 } 62 if(vec[i].right != '-') 63 { 64 res[i].right = &res[vec[i].right - '0']; 65 } 66 else 67 { 68 res[i].right = NULL; 69 } 70 } 71 // bool型数组帮助找到根节点 72 vector<bool> flag; 73 // 树的根节点 74 BinTreeNode<int> * root = NULL; 75 // 找到根节点,flag仍然为0的那个就是,当然这里还没有给head赋值 76 for(int i=0; i<n; i++) 77 { 78 flag.push_back(0); 79 } 80 for(int i=0; i<n; i++) 81 { 82 if(vec[i].left != '-') 83 flag[vec[i].left-'0'] = 1; 84 if(vec[i].right!= '-') 85 flag[vec[i].right-'0'] = 1; 86 } 87 88 for(int i=0; i<n; i++) 89 { 90 if(flag[i] == 0) 91 { 92 root = &res[i]; 93 break; 94 } 95 } 96 97 BinTreeNode<int> * p; 98 vector<int> result; 99 queue<BinTreeNode<int> *> que; 100 que.push(root); 101 102 while(p != NULL) 103 { 104 if(que.size() == 0) 105 break; 106 p = que.front(); 107 if(p -> left == NULL && p -> right == NULL) 108 { 109 result.push_back(p->data); 110 } 111 que.pop(); 112 if(p -> left != NULL) 113 { 114 que.push(p -> left); 115 } 116 if(p -> right != NULL) 117 { 118 que.push(p -> right); 119 } 120 } 121 int len = result.size(); 122 for(int i=0; i<len ; i++) 123 { 124 cout << result[i]; 125 if(i != len - 1) 126 cout << " "; 127 } 128 return 0; 129 }
按照惯例粘一下AC的结果: