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的作用用来判断输出空的,不能够把数字一起输出,改成如第二张图那样,把他们拆开,这样对了。

posted on 2019-06-02 16:16  拜伦。  阅读(312)  评论(0编辑  收藏  举报

导航