DS作业06-图

1.本周学习总结(0--2分)

1.1思维导图

1.2谈谈你对图结构的认识及学习体会。

图这一章的学习,是经过树学习后,难得一章重新寻找到感觉的学习。因为这一章比较少用递归,使用的是结构体,很多东西我有基础。所以学起来快很多,而且感觉也很熟悉,有一种似曾相识的感觉。图的结构主要靠2个变量,边和顶点数。这2个变量串起来组成的2中方法:邻接表和邻接矩阵。结构上还是学过的链表和2维数组,所以学起来还是比较顺利。两种不同的存储有各自的优缺点,适用不同的题目。虽然在变成题目代码的实现上还是有难度,但是还是思路想得到。比如pta的好几道编程题,我直接参考数组的写法,跳过了图的写法。如果用图,会复杂点,但是就是增加一步建图的过程,其余的思路都是一样。结构体的定义上不管邻接矩阵还是邻接表都是比较容易。这一章的学习,总体上感觉不错,以前很长一段时间都被树搞的很迷,终于找到点感觉。当然了这一章也是有难度的,难在一些有名的算法的实现。比如基本的一些寻找路径的算法,Dijkstra和Floyd算法,虽然Floyd算法更精短,一些深度,广度遍历的算法,这些算法背下来,能用就行。思路都了解,大体上不会很难,都会使用。

2.PTA实验作业(6分)

2.1.题目1:题目名称

2.1.1设计思路(伪代码)

宏定义无穷大INF为32767 
宏定义 MAXV 为1001
宏定义邻接矩阵 g[MAXV][MAXV]/数组 visited[MAXV]={0};
定义 count 为1来判断是否为连通图
Main:
{
定义 i,n,e分别表示循环变量、顶点数、边数 /定义浮点型数据 sum为修路成本
输入 n,e 顶点数 边数 
 if  n-1大于e then  //不能够建成图
cout<<-1
 return 0
CreateGraph(n, e)//建邻接矩阵
 sum=Prim(n,1)//调用prim函数返回sum
 if count==n then //说明图连通
 cout<<sum
 else   
 输出-1
 end if 
    return 0
}

void CreateGraph//建邻接矩阵
{
定义 i,j循环变量
定义 a, b, c;分别对应两个城镇的编号以及该道路改建的预算成本
for i = 0 to n //初始化邻接矩阵
  for j = 0 to n do
g[i][j]==0
end for
end for
 for i = 1 to e do//赋值矩阵
 输入 a,b,c
g[a][b] =g[b][a]= c;
 end for
}


int Prim//计算最小值
{
定义i, j表示循环变量 
定义min为最低的费用,index用来存小路径下标
定义 数组 lowcost[MAXV],close[MAXV],
定义 cost = 0表示最低成本, 

for i = 1 to n //给2个数组置初值 
        lowcost[i] = g[v][i];
        close[i] = v; 
 end for
 for i = 1 to n  
     min = INF
  定义 flag=0//用来判断这个费用是否符合最低费用要求,如果符合计算进去
 for j = 1 to n //从剩下的城市中找最近的点 
   if lowcost[j] 不等于 0且lowcost[j] 小于 min)  then //寻找最少费用
min = lowcost[j];
 index = j;
flag=1;
end if 
end for 
if flag不为0 then //该费用符合题意
cost += min;//加入cost
count++;
lowcost[index] = 0;//记录这个结点访问过
for j=1to n do  //调整最短路径,最少费用      
if lowcost[j] 不等于 0且g[index][j]小于lowcost[j then//修改最少费用             
lowcost[j] = g[index][j];
close[j] = index
end for
end for
return cost//返回费用
}

2.1.2代码截图



2.1.3本题PTA提交列表说明。


+Q1: 第一个提交是没有考虑到边和顶点数不符合关系,这个时候不能够建成功矩阵。
+A1:在主函数判断的时候增加:

+Q2:没有判断连通不连通,万一图是不连通的情况下,也不符合题目要求。
+A2:百度了一个方法,初始化一个
count:

变量用来记录成功的顶点数。如果遍历完成后成功的顶点数和初始n相同,说明每一个顶点都遍历到了,这是一个连通图。否则不符合。

+Q3:25分后最大N这里过不去,不知道怎么解决了。

2.2 题目2

2.2.1设计思路(伪代码)

定义vector和set容器
定义v,e,k,分别是无向图的顶点数、边数、以及颜色数。
定义num是组别的个数
定义动态数组mp;
输入各顶点之间的关系,类似于建邻接矩阵
for i=0 to e 
依次输入e个组数据
打入动态数组mp中//输入成有向图这种情况
end for
输入num组判断颜色的个数

do while 

flag初始化为1
每次循环都将容器 s 清空

for int i = 1 to v
输入各点对应涂的颜色,并且将颜色输入容器 s 中//相同颜色只需要记录一次
end for

if 容器 s 大小不等于颜色总数k then  flag=0该方案不行

for int i = 1 to v//遍历每个节点
  for int j = 0 to mp[i].size()// 遍历与该节点相邻的节点
     if 两相邻节点颜色相同 then 不符合涂色方案,跳出循环
   end for
     if flag=0 then 跳出循环//不合法
end for
if(flag=1) then 输出符合方案
 else  输出不符合

end while

2.2.2代码截图

2.2.3本题PTA提交列表说明。


+Q1:第一次容器内的数循环没有清空,导致只能过一个测试点。
+A1:在循环开始前加入:

+Q2:一开始不知道如何判断颜色是否合理,不知道怎么判断。
+A2:百度一下,百度是把用过顶点的颜色信息存在数组里面,类似哈希数组的方法,这一遍历这个数组就知道这个颜色使用过没,是否符合题意。

2.3 题目3

2.3.1设计思路(伪代码)

定义邻接矩阵g[10001][10001],
定义顶点数v,边数e,循环变量i,
定义变量x,y用来存放结点关系数据
main:
{
   定义浮点型数据 n,m来求最后所占比率
 输入顶点数v和边数e
 while e--   //构建邻接矩阵
        输入边关系 x  y
        g[x][y] = g[y][x] = 1
 end while

 for i=1 to v 
 定义浮点型数据 n,m//记录比率
        n=v  
        m=bfs(i) //调用bfs函数
 end for
  return 0
}

bfs(int z)//广度遍历
{   
定义数组vis[10001]=0 记录被访问过的结点
  last = z表示记录每层的最后一个元素
  tail表示用于记录每一层压入栈时的结点
定义 level = 0 用于判断距离是否合题意为6
定义count=1//记录符合的结点数目
建int型栈q
z入栈
将vis[z]置为1//访问成功标记
while q不为空 
    z = q.front()//取栈顶元素z
    q.pop()//使用过的元素去掉
for i = 1to v  //广度遍历
   if g[z][i] 等于1 && vis[i]等于 0 then//符合题意
       count++;
       vis[i] = 1;
       q.push(i);
       tail = i;
end if 
end for 

if last 等于z then////这一层全部弹出,准备开始下一层,当前层最后一个元素(last) 记录下来         level++;
    last = tail;//记录最后一个元素 
end if 

if  level 等于 6 break //符合题意距离6,跳出循环

end while

return count//返回符合的结点数

}

2.3.2代码截图


2.3.3本题PTA提交列表说明。

+Q1:记录2个比例的时候未使用浮点数,导致结果有误差,没有按题目输出要求输出。
+A1:改成double定义数后输出结果格式正确了。

+Q2:一开始不知道怎么处理距离为6这个问题,使用了深度遍历,查到了到就结束程序,不能够多重方向寻找
+A2:改成广度遍历,加上vis数组判断,这样所有结点都能够访问一遍,所有点都不会漏掉。

+Q3:重新寻找一层的时候没有记住上一层最后一个结点,倒是寻找重复了,
+A3:用last更新上一层的最后一个结点,保证寻找的时候不会重新走老路,记录的都是新的结点。

3、上机考试错题及处理办法(-2--2分)

3.1截图错题代码

3.1.1:题目

3.1.2:代码



3.1.3 错的原因及处理方法


+原因:这个格式错误我一开始没想到是输出的问题,因为我只试了bfs函数,发现没问题,结果试了dfs函数发现少了空格,才知道是flag的问题,这里的flag是个全局变量,忘记更改他的值了,结果成这样:

+更改方法:在flag输出了第一个非空后把flag变为1,这样后面的空格就可以出来了。

3.2.1题目

3.2.2代码


3.2.3错的原因及处理办法

+原因:遍历循环查找结点的时候指针忘记移动:少了p=p->nextarc,这一步:
+处理方法:

+原因:输出的时候掉了第一个数据:

+处理方法:
输出的时候这里有问题:

这里flag判断一下直接把第一个数跳过了,flag的作用用来判断输出空的,不能够把数字一起输出,改成这样,把他们拆开:

原文地址:https://www.cnblogs.com/zhouqb/p/10963212.html