DS博客作业06--图

1.思维导图及学习体会

1思维导图

DS博客作业06--图_第1张图片

2.谈谈你对图结构的认识及学习体会

  • 1. 在我看来,图就是一堆顶点和边的集合,既然是图可以分为有向图和无向图、还可以分为连通图和非连通图。在图结构中,每个元素可以有零个或多个前驱元素,也可以有零个或多个后继元素,也就是说元素之间的关系是多对多的。图的存储方法有邻接矩阵和邻接表,邻接矩阵顾名思义,是一个矩阵,存储着边的信息的矩阵,而顶点则用矩阵的下标表示,如果是无向图则有A [j ,i] = A[i, j],所以无向图的邻接矩阵是一个对称矩阵;但如果是有向图,则不一定是一个对称矩阵。邻接表可以有效避免内存的浪费,邻接表用一个一维数组存储顶点,利用邻接表建图时候,需要创建多个结构体,如结点类型的结构体,头结点也弄一个结构体,还有邻接表一个结构体。两种不同的存储有各自的优缺点,适用于不同的地方。如果是稀疏图或者需要特定用途的话采用领阶矩阵存储结构的好,反之如果是需要插入删除等操作的话采用邻接表的好。
  • 2.图的遍历有广度优先遍历BFS和深度优先遍历DFS,不过书上给两种算法的代码对应的都是针对于连通图的算法,还有最小生成树的算法有prim算法和克鲁斯卡尔算法,克鲁斯卡尔算法的时间复杂度与边e有关,克鲁斯卡尔算法时间复杂度O(e^2),prim算法时间复杂度与图的顶点n数有关,其时间复杂度为O(n^2)。还有求最短路径的算法:Dijkstra和Floyd算法,虽然Floyd算法更精短,但真是理解不来,时间复杂度也不少O(n^3),按老师所说的还算不错了。
  • 3.图的话结构体多了很多,光是要记住的类型名也很多,因为结构体多,所以有时候在调用一些结构体里的数据时就容易搞错,也因为Devc有时候不能够像vs那样直接显示结构体里包含的成员,所以这段时间也改用vs来编写代码了,这次pta上的题目大都可以看书本上的代码来写,或改进些

2.PTA实验作业

2.1.题目1:7-3 六度空间

“六度空间”理论又称作“六度分隔(Six Degrees of Separation)”理论。这个理论可以通俗地阐述为:“你和任何一个陌生人之间所间隔的人不会超过六个,也就是说,最多通过五个人你就能够认识任何一个陌生人。”如图1所示。
“六度空间”理论虽然得到广泛的认同,并且正在得到越来越多的应用。但是数十年来,试图验证这个理论始终是许多社会学家努力追求的目标。然而由于历史的原因,这样的研究具有太大的局限性和困难。随着当代人的联络主要依赖于电话、短信、微信以及因特网上即时通信等工具,能够体现社交网络关系的一手数据已经逐渐使得“六度空间”理论的验证成为可能。

假如给你一个社交网络图,请你对每个节点计算符合“六度空间”理论的结点占结点总数的百分比。

2.1.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) //调用bfs函数
   end for
   return 0

int bfs(int z)
   定义数组vis[10001]=0 表示是否被访问过的结点
   定义 last = z表示记录每层的最后一个元素
   i定义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//一层全部从栈弹出,准备开始弹下一层,弹出的数等于当前层最后一个元素,并记录与last 
        level++;
        last = tail;//记录最后一个元素 
        end if 
        if  level 等于 6 break //符合题意的路径节点       
    return count

2.1.2代码截图

DS博客作业06--图_第2张图片

DS博客作业06--图_第3张图片

2.1.3本题PTA提交列表说明。

DS博客作业06--图_第4张图片

  • Q1:起初以为这是深度遍历问题,想的是与这个结点距离为6,那么便从起点出发,一旦找到长度6的顶点便返回
  • A1:然后试了好几次测试样例都是错的,问了舍友才知道应该用广度遍历,广度遍历的话找与起点有联系的点,并以此扩散,这样可以找到全部符合题意的点,而不是像深度遍历一样只能找一路
  • Q2:知道深度遍历行不通,就将函数题的邻接矩阵广度遍历拿来用,再慢慢改动点
  • A2:基本就是重写代码了,一堆宏定义都是是舍友教的,从编译错误那里开始就改成了广度遍历法
  • Q3:提交pta,发现还是不对,输出出来的结果比起答案少很多
  • A3:在遍历中,我没有对一旦level等于6就退出循环,导致最后结果比起来少了很多

2.2.题目1:7-4 公路村村通

现有村落间道路的统计数据表中,列出了有可能建设成标准公路的若干条道路的成本,求使每个村落都有公路连通所需要的最低成本。

2.2.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)//计算最低成本 调用prim函数 
    if count==n then 
    输出sum
    else    输出-1
   end if 
    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数组和close数组置初值 
        lowcost[i] = g[v][i];
        close[i] = v; 
    end for
    for i = 1 to n  do
        min = INF
        定义 flag=0//用来判断这一层是否有最低费用
        for j = 1to 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=1to n do  //进行调整      
            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.2.2代码截图

DS博客作业06--图_第5张图片

DS博客作业06--图_第6张图片

DS博客作业06--图_第7张图片
DS博客作业06--图_第8张图片

2.2.3本题PTA提交列表说明。

DS博客作业06--图_第9张图片

  • Q1:如果无法畅通的情况处理不来
  • A1:后来在每次循环时候将最小min等于无穷大INF,如果最小的路径等于无穷大,则说明没有路径即无法正常畅通。
  • Q2:一开始是看书上的prim算法写的,没怎么改动,主要是那个最低费用的一开始不知道怎么写,然后先试着提交一下还是有分的
  • A2:后来我就设了min和index分别来存最少的路费和对应的点,并通过最后求一行的cost来计算最低费用
  • Q3:最后在第一层循环内有个地方错误
  • A3:就是要在每次要将index所在第一行初始化,就是lowcost[index]要置为0,否则会错误,不能跳进循环

2.3.题目1:7-1 图着色问题

图着色问题是一个著名的NP完全问题。给定无向图G=(V,E),问可否用K种颜色为V中的每一个顶点分配一种颜色,使得不会有两个相邻顶点具有同一种颜色?

但本题并不是要你解决这个着色问题,而是对给定的一种颜色分配,请你判断这是否是图着色问题的一个解。

2.3.1设计思路(伪代码)


宏定义数组 visited[501]={0},d[501],k=0
宏定义邻接矩阵a[501][501]及循环变量与一些变量:v,e,z,x,y,i,j,n;
void dfs(int i)
{
       定义 j;
       d[k++]=i;
       visited[i]=1;
       forj=1to v do       
           if(a[i][j]等于1 并且 visited[j]等于0 then dfs(j);
           end if
       end for
}
void dfs1()
{
    定义 i;
    for i=1 to v
    
         if visited[i]等于0 then dfs(i); //没被访问过
    end for
}

int main()
{
    输入v、e、z;
    for i=0 to e
    
      输入变关系x、y;
      a[x][y]=a[y][x]=1;
    end for
    dfs1();
    输入n;
    while n--
   
     初始化 b[501]={0},c[501],e[501],sum=0,flag=1;
     for i=1 to v;i++)
     
        输入c[i];
        b[c[i]]++;
        if b[c[i]]等于1 then sum++;
     end for 
     if sum不等于z then flag=0;
     end if
     for i=0 to k do e[i]=c[d[i]]
     end for
     for i=0 to k
     
         forj=0 to k     
        if a[d[i]][d[j]]等于1并且e[i]等于e[j] then
       
            flag=0;
            break;
       end if 
       
        if flag等于0 then break;
    end for 
     if flag等于0 输出No
     else 输出Yes
     end if 
end while  
 return 0
}

2.3.2代码截图

DS博客作业06--图_第10张图片
DS博客作业06--图_第11张图片
DS博客作业06--图_第12张图片
DS博客作业06--图_第13张图片

2.3.3本题PTA提交列表说明。

DS博客作业06--图_第14张图片

  • Q1:一开始提交中只有最小图和最大图正确
  • A1:在修改好多次后还是没能得到测试样例的正确答案,最后实在是写不动了,让舍友教我,然后才会写的
  • Q2:舍友说这道题是广度遍历...我写的是深度遍历
  • A2:主要是通过dfs的递归调用来实现遍历,本来我是写的是广度遍历的,因为自己画图的时候自己是有点像广度遍历那样,所以再写代码时候就以为用深度遍历,然后越搞越复杂,写了百来行代码,还搞不出来

3上机考试错题及处理办法

3.1.1截图错题代码:6-2 jmu-ds-图邻接表操作

错误
DS博客作业06--图_第15张图片

3.2 错的原因及处理方法

DS博客作业06--图_第16张图片

深度遍历时候,指针指向下一个的时候,考试时候想错了,然后放在了如果没被遍历过的if语句中,导致超时,将语句放在if语句外就可以了

3.2.1截图错题代码:6-3 jmu-ds-拓扑排序

错误
DS博客作业06--图_第17张图片

DS博客作业06--图_第18张图片
DS博客作业06--图_第19张图片

3.2 错的原因及处理方法

改正

DS博客作业06--图_第20张图片
DS博客作业06--图_第21张图片
DS博客作业06--图_第22张图片

可能是考试时候打得太快了...把大写G写成了小写g,while也写错了,写成了whlie...

3.1.1截图错题代码:7-1 六度空间

错误
DS博客作业06--图_第23张图片
DS博客作业06--图_第24张图片

DS博客作业06--图_第25张图片

3.2 错的原因及处理方法

DS博客作业06--图_第26张图片

忘记用tail记录下每行的最后一个没被遍历的数,还有当时看题目搞错题目意思了,以为少于6是当等于7时候退出循环,主要是考试前特别慌这最后一场考试,经常去写去看这些pta代码,基本到最后都快能背下来了,连变量名都没换

3.1.1截图错题代码:7-2 公路村村通

错误
DS博客作业06--图_第27张图片
DS博客作业06--图_第28张图片
DS博客作业06--图_第29张图片

DS博客作业06--图_第30张图片

3.2 错的原因及处理方法

DS博客作业06--图_第31张图片

DS博客作业06--图_第32张图片

忘记考虑了另外就是当数目不对时候也是不符合的情况,也要输出-1,还有就是之前不好理解的将最后一个没被遍历的那一行的首个置为0,在考试时候还是没注意到,又忘记了,最后还是没时间就没去细想了

你可能感兴趣的:(DS博客作业06--图)