本章主要学习了树和二叉树相关知识,包括二叉树的性质和存储结构(双亲表示法、孩子表示法、孩子兄弟法),二叉树的前、中、后序遍历算法等,还了解了哈夫曼树和哈夫曼编码的构造方法,以及森林与二叉树之间的相互转换方法。
实验课老师带领我们做了“深入虎穴”这道题:
7-2 深入虎穴 (30 分)
著名的王牌间谍 007 需要执行一次任务,获取敌方的机密情报。已知情报藏在一个地下迷宫里,迷宫只有一个入口,里面有很多条通路,每条路通向一扇门。每一扇门背后或者是一个房间,或者又有很多条路,同样是每条路通向一扇门…… 他的手里有一张表格,是其他间谍帮他收集到的情报,他们记下了每扇门的编号,以及这扇门背后的每一条通路所到达的门的编号。007 发现不存在两条路通向同一扇门。
内线告诉他,情报就藏在迷宫的最深处。但是这个迷宫太大了,他需要你的帮助 —— 请编程帮他找出距离入口最远的那扇门。
输入格式:
输入首先在一行中给出正整数 N(<),是门的数量。最后 N 行,第 i 行(1)按以下格式描述编号为 i 的那扇门背后能通向的门:
K D[1] D[2] ... D[K]
其中 K
是通道的数量,其后是每扇门的编号。
输出格式:
在一行中输出距离入口最远的那扇门的编号。题目保证这样的结果是唯一的。
输入样例:
13
3 2 3 4
2 5 6
1 7
1 8
1 9
0
2 11 10
1 13
0
0
1 12
0
0
输出样例:
12
跟上节课讲题思路一样,首先考虑数据结构,根据一个门后面又有很多门,自然就联想到“树”的结构,而每扇门都能包含其所通向的门的信息,即要存储每个结点的孩子结点的信息,老师一开始采用的是二维数组来存储,思考后发现这是一个稀疏矩阵,会导致大量空间的浪费。因此为了避免浪费空间,可以采用结构体数组的方式,结构体数组由数据域(通向的门的个数)和指针域(通向的门的编号)组成。
1 typedef struct{ 2 int doors;//门的数量 3 int *p;//指向后面的门的编号序列 4 }node;
代码由多个实现不同功能的函数构成。
- 读入门的信息,返回根所在的门牌号
1 int Input(node *a, int n){//读入n扇门的信息给a数组,返回根所在的门牌号(下标) 2 int i,j; 3 bool *vi; 4 vi=new bool[n+1]; 5 for(i=1;i<=n;++i)//初始化vi数组的全部元素为false 6 vi[i]=false; 7 for(i=1;i<=n;++i){//读入n扇门的信息 8 cin>>a[i].doors; 9 if(a[i].doors!=0){ 10 a[i].p=new int[a[i].doors];//为a[i].p申请空间 11 for(j=1;j<=a[i].doors;++j){ 12 cin>>a[i].p[j-1]; 13 vi[a[i].p[j-1]]=true; 14 } 15 } 16 else//doors为0 17 a[i].p=NULL; 18 } 19 for(i=1;i<=n;++i)//找根节点所在的下标 20 if(!vi[i]) return i; 21 }
- 利用层次遍历得到树最深的结点,返回遍历的最后一个节点的编号
1 int Level(node *a, int r){//从a[r]开始对a进行层次遍历,并返回遍历的最后一个节点的编号 2 queue<int> q; 3 int t; 4 q.push(r); 5 while(!q.empty()){ 6 t=q.front(); 7 q.pop(); 8 if(a[t].doors!=0){//t号门后面还有门,后面的门入队 9 for(int i=0;i<a[t].doors;++i) 10 q.push(a[t].p[i]); 11 } 12 } 13 return t; 14 }
- 最后是主函数
1 int main(){ 2 node *a;//a用于存储整棵树 3 int i,j,k; 4 int n,root; 5 cin>>n; 6 a=new node[n+1]; 7 root=Input(a,n); 8 cout<<Level(a,root)<<endl; 9 return 0; 10 }
这次实验课后,感觉自己思考、入手问题的能力有所加强,分析问题能力也有所提高,但是打代码的能力还是比较弱,因此还是要自己多多练习,另外本章的概念比较多也难懂,要再多花时间看看书本,熟悉所有概念。
原文地址:https://www.cnblogs.com/Daylight-Deng/p/10810430.html
时间: 2024-11-05 20:27:57