DS博客作业06--图
1.本周学习总结
1.1思维导图
1.2谈谈你对图结构的认识及学习体会
1.对于图首先学到的就是它的遍历,图的遍历比较经常用的是深度优先遍历和广度优先遍历。图的深度优先遍历是从初始点v出发,以纵向的方式逐渐访问各个顶点,一旦找不到相邻的顶点就回退,需要递归的过程,广度遍历是类似层次遍历,利用队列来一一访问。
2.接着就是学Prim算法和Kruscal算法了。Prim和Kruscal算法,Prim算法是多次寻找邻边的权重最小值,而Kruskal是需要先对权重排序后查找的,Kruskal在算法效率上是比Prim快的,因为Kruskal只需一次对权重的排序就能找到最小生成树,而Prim算法需要多次对邻边排序才能找到。但是个人是比较喜欢Prim算法的。
3.然后也学习了Dijkstra算法。该算法是在无向图 G=(V,E) 中,假设每条边 E 的长度为 w,找到由顶点 V0 到其余各点的最短路径。其主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止。
4.最后就是学习拓扑排序了,拓扑排序是将一个有向无环图G的所有的顶点排成一个线性序列,使得有向图中的任意的顶点u 和 v 构成的弧,(u, v) 属于该图的边集,并且使得 u 始终是出现在 v 前面。并且只有有向无环图才可以进行拓扑排序。该算法的思想:一:找到有向无环图中没有前驱的节点(或者说是入度为0的节点)输入;二:然后从图中将此节点删除并且删除以该节点为尾的弧。
5.个人认为这次的学习比树还要简单点,因为图的递归的算法用的比较少,所以我会觉得简单点。而且这次的题目有许多有使用栈和队列的算法,而我个人对这两个算法比较理解,所以结合起来学的话会简单些。
2.PTA实验作业
2.1.题目1:7-1 图着色问题
2.1.1设计思路(伪代码)
定义vector和set容器
定义v,e,k,分别是无向图的顶点数、边数、以及颜色数。
定义num是组别的个数
定义动态数组mp;
输入各顶点之间的关系,类似于建邻接矩阵
for i=0 to e
依次输入e个组数据
打入动态数组mp中
end for
输入num组判断颜色的个数
while num--不为零
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.1.2代码截图
2.1.3本题PTA提交列表说明
- Q1:一开始的时候容器内的数循环没有清空,导致只能过一个测试点。
- A1:后面上网查了一下资料,增加了s.clear();就通过了。
- Q2:一开始不知道如何判断颜色是否合理。想了好久还是没想出来,想到了老师之前说过的网上有许多优秀的代码,所以就去网上查了。
- A2:百度一下,百度是把用过顶点的颜色信息存在数组里面,类似哈希数组的方法,这一遍历这个数组就知道这个颜色使用过没,是否符合题意。
- A3:讲真的这题一开始我不是这样写的,之前的写得复杂得多了,然后去网上有看到一个比较简单的写法,所以就用那种写法了。这种写法最大的不同就是多了一个容器,这个容器之前并没学过,通过这题又多学了个新知识。
2.2 题目2:7-3 六度空间
2.2.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 do
n=v
m=bfs(i)
end for
return 0
int 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 do //广度遍历方法
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
level++
last = tail
end if
if level 等于 6 break
return count
2.2.2代码截图
2.2.3本题PTA提交列表说明
- Q1:一开始记录一个数据的时候未使用浮点数,导致结果有误差,没有按题目输出要求输出。
- A1:然后多输出几次就找到错误了,改成double定义数后输出结果格式正确了。
- Q2:一开始不知道怎么处理距离为6这个问题,使用了深度遍历,因为我个人认为深度遍历比较好理解,但是深度遍历查到了到就结束程序,不能够多重方向寻找。
- A2:后面改成用广度遍历,加上vis数组进行判断,这样所有结点都能够访问一遍,不会有漏掉的。
2.3 题目3:7-4 公路村村通
2.3.1设计思路(伪代码)
宏定义无穷大INF为32767 MAXV 为1001
宏定义邻接矩阵 g[MAXV][MAXV]以及数组 visited[MAXV]={0};
定义 count 为1来判断是否为符合要求
int main()
{
定义 i,n,e分别表示循环变量、顶点数、边数
定义浮点型数据 sum为成本
输入 n,e
if n-1大于e then
输出-1
return 0
end if
CreateGraph(n, e)
sum=Prim(n,1)
if count==n then
输出sum
end if
else 输出-1
return 0
}
void CreateGraph(int n, int e) //创建邻接矩阵
{
定义 i,j,a, b, c;
for i = 0 to n; do//初始化
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(int n, int v)
{
定义 数组 lowcost[MAXV],close[MAXV], cost = 0表示最低成本, i, j表示循环变量 min为最低的费用,index用来存下标
for i = 1 to n
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
count++
end if
lowcost[index] = 0;
for j=1 to n //进行调整
if lowcost[j] 不等于 0且g[index][j]小于lowcost[j then//修改数组的值
lowcost[j] = g[index][j]
close[j] = index
end if
end for
end for
return cost
}
2.3.2代码截图
2.3.3本题PTA提交列表说明
- Q1:一开始对于无法畅通的这种情况处理不好。老是打不出来。
- A1:后来在每次循环时候将最小min等于无穷大INF,就是说如果最小的路径等于无穷大,那么久说明没有路径久无法正常畅通。
- Q2:一开始prim算法是看书上的代码写的,没怎么改动,主要是就是那个最低费用的一开始不懂写,然后久先试着提交一下,还是有几分的。
- A2:后来我就设了min和index分别来存最少的路费和对应的点,然后通过求最后一行的cost来计算最低费用,就正确了。
3.上机考试错题及处理办法
3.1.1截图错题代码:6-2 jmu-ds-图邻接表操作
3.1.2 错的原因及处理方法
-
修改后:
-
一开始代码写完后就直接上交了,但是发现深度遍历这部分错误了,所以就进行调试,在调试过程中发现是超时了,然后我就想应该是控制循环的部分出错了,所以就再仔细看看代码并回想当时是怎么写的,发现是指针指向下一个的位置放错了,导致超时,当换了位置之后,发现还是错误,是格式错误,这个就比较简单了,只要看看输出的部分应该就可以看出来,但是我看了好久,还是没看出来,真的是无语,但最后我用题目那里的输出格式的空格复制粘贴上去,才发现原来是输出的空格我抖多点了一下,哇靠这个贼难受,改完之后就对了。
3.2.1截图错题代码:6-3 jmu-ds-拓扑排序
3.2.2 错的原因及处理方法
- 修改之后:
- 我写完就提交了,不出所料,还是和往常一样有错误,然后我就放到运行一下,发现是这样的:
然后我就发现错了,发现输出的时候掉了第一个数据,原来是漏掉了p=p->nextarc,这一步,进行修改之后第一个数据是出来了,但是还是错了,然后在看看,发现是输出的问题,就如第一图那样,空格和数据是一起输出的,然后才想起他们,不能放在一起,然后就用flag判断一下直接把第一个数跳过了,flag的作用用来判断输出空的,不能够把数字一起输出,改成如第二张图那样,把他们拆开,这样对了。