赞
踩
本文内容基于《算法笔记》和官方配套练题网站“晴问算法”,是我作为小白的学习记录,如有错误还请体谅,可以留下您的宝贵意见,不胜感激。
本节讨论的“树”是指一般意义上的树,即子结点个数不限且子结点没有先后次序的树,而不是上文中讨论的二叉树。
首先来回顾二叉树的结点的定义,可以注意到它是由数据域和指针域组成的,其中左指针域指向左子树根结点的地址,右指针域指向右子树根结点的地址。借鉴这种定义方法,对一棵一般意义的树来说,可以仍然保留其数据域的含义,而令指针域存放其所有子结点的地址(或者为其开一个数组,存放所有子结点的地址)。不过这听起来有点麻烦,所以还是建议在考试中使用其静态写法,也就是用数组下标来代替所谓的地址。但这样可能会导致内存使用超过题目限制,因此可以采用vector模板来存储结点。(摘自算法笔记)
区别于二叉树,树没有左右子树一说,因此在DFS中,树只有先根和后根遍历,区别在于根和子节点的先后访问顺序,子节点代表岔道口,当不存在结点时即代表走到了死胡同。
树的层次遍历就是BFS,这个没有什么不同。通过例题来感受:
在保证除输出序列改变而题干不变的情况下,分别采用先根、后根和层次遍历实现,用静态写法实现代码如下,注意递归边界的体现:
DFS:
#include<cstdio> #include<vector> using namespace std; const int MAXN = 51; struct Node{ vector <int> child; }node[MAXN]; int count = 1 , n; void preOrder(int root){ //先根 printf("%d", root); if(count <= n - 1) { printf(" "); count++; } for(int i = 0; i < node[root].child.size(); i++) //第二个表达式就是递归边界 preOrder(node[root].child[i]); } void postOrder(int root){ //后根 for(int i = 0; i < node[root].child.size(); i++) //第二个表达式就是递归边界 preOrder(node[root].child[i]); printf("%d", root); if(count <= n - 1) { printf(" "); count++; } } int main(){ scanf("%d", &n); for(int i = 0; i <= n - 1; i++){ int k; scanf("%d", &k); for(int j = 0; j <= k - 1; j++){ int temp; scanf("%d", &temp); node[i].child.push_back(temp); } } preOrder(0); }
BFS:
#include<cstdio> #include<vector> #include<queue> using namespace std; const int MAXN = 51; struct Node{ vector <int> child; }node[MAXN]; int count = 1 , n; void BFS(int root){ queue <int> qe; qe.push(root); while(!qe.empty()){ int top = qe.front(); qe.pop(); printf("%d", top); if(count <= n - 1) { printf(" "); count++; } for(int i = 0; i < node[top].child.size(); i++) qe.push(node[top].child[i]); } } int main(){ scanf("%d", &n); for(int i = 0; i <= n - 1; i++){ int k; scanf("%d", &k); for(int j = 0; j <= k - 1; j++){ int temp; scanf("%d", &temp); node[i].child.push_back(temp); } } BFS(0); }
1.树的高度
树是带有递归性质的,所以求树的高度就是求最大递归深度,用计数器即可实现,完整代码如下:
#include<cstdio> #include<vector> using namespace std; const int MAXN = 51; struct Node{ vector <int> child; }node[MAXN]; int count = 1 , n; int maxans = -1; void preOrder(int root , int index){ if((int)node[root].child.size() == 0 && maxans < index) maxans = index; //这就是递归边界,只是隐含在了下面的循环中,最好还是写上这句 for(int i = 0; i < node[root].child.size(); i++) //第二个表达式就是递归边界 preOrder(node[root].child[i] , index + 1); } int main(){ scanf("%d", &n); for(int i = 0; i <= n - 1; i++){ int k; scanf("%d", &k); for(int j = 0; j <= k - 1; j++){ int temp; scanf("%d", &temp); node[i].child.push_back(temp); } } preOrder(0 , 1); printf("%d", maxans); }
2.树的结点层号
老问题了,可以采用BFS+计数器的方式实现,也可以采用DFS+计数器的方式实现,把计数器放到结构体里就好,每向下一层就动态更新层号,完整代码如下:
#include<cstdio> #include<vector> #include<queue> using namespace std; const int MAXN = 51; struct Node{ vector <int> child; int step; }node[MAXN]; int count = 1 , n; void BFS(int root){ queue <int> qe; qe.push(root); node[root].step = 1; while(!qe.empty()){ int top = qe.front(); qe.pop(); for(int i = 0; i < node[top].child.size(); i++){ qe.push(node[top].child[i]); node[node[top].child[i]].step = node[top].step + 1; } } } int main(){ scanf("%d", &n); for(int i = 0; i <= n - 1; i++){ int k; scanf("%d", &k); for(int j = 0; j <= k - 1; j++){ int temp; scanf("%d", &temp); node[i].child.push_back(temp); } } BFS(0); for(int i = 0; i <= n - 1; i++){ printf("%d", node[i].step); if(i < n - 1) printf(" "); } }
3.树的路径和
记录走过的路径权值和,求到达叶结点时本条路径上的权值和,将所有叶结点的权值和相加即可。采用计数器实现,每进入一个子结点就将原有路径上的权值和传入子节点。完整代码如下:
#include<cstdio> #include<vector> using namespace std; const int MAXN = 51; struct Node{ int data; vector <int> child; }node[MAXN]; int n , ans = 0; void preOrder(int root , int w){ if((int)node[root].child.size() == 0) ans += w; for(int i = 0; i < node[root].child.size(); i++) //第二个表达式就是递归边界 preOrder(node[root].child[i] , w + node[node[root].child[i]].data); } int main(){ scanf("%d", &n); for(int i = 0; i <= n - 1; i++) scanf("%d", &node[i].data); for(int i = 0; i <= n - 1; i++){ int k; scanf("%d", &k); for(int j = 0; j <= k - 1; j++){ int temp; scanf("%d", &temp); node[i].child.push_back(temp); } } preOrder(0 , node[0].data); printf("%d", ans); }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。