数据结构第七周笔记——图(中3)(慕课浙大版本--XiaoYu)

简介: 小白专场,实现案例:哈利波特的考试,并进行逐句讲解

小白专场:哈利 波特的考试-C语言实现

小白-HP.1 题意理解

网络异常,图片无法展示
|

样例第一列表示动物的个数(也就是顶点的个数)      第二列表示边的个数

D是最短距离的矩阵,记录从顶点i到顶点j之间的最短距离

Harry究竟应该带哪只动物去的问题的时候,首先检查每一行里面最大的那个数字,最大的那个数字代表着第一个动物变成最大数字的那个动物是最麻烦的,无穷符号指当前的那个动物

要带什么动物去会使我们最难变的动物变成最好变的呢?答案是动物4号,它最难变的咒语是70

小白-HP.2 程序框架搭建

intmain()

{

   读入图;

   分析图;

   return0;

}

代码实际演示

intmain()

{

   //有两种图,一种邻接表的,一种邻接矩阵的。这里选择了邻接矩阵的方法来表示图

   GraphG=BuildGraph();

   FindAnimal( G );

   return0;

}

//FindMaxDist(i)是最大距离,对第i个动物去求他所有最短距离里面的最大值,要求的是所有这些最大值里面的最小值

//FindMin是最小距离

网络异常,图片无法展示
|

小白-HP.3 选择动物

voidFindAnimal(MGraphGraph)

{

   WeightTypeD[MaxVertexNum][MaxVertexNum],MaxDist,MinDist;

   VertexAnimal, i;

   

   Floyd(Graph , D);

   

   //FindMin:从每个动物i的最短距离的最大值中,找到最小值MinDist,以及对应的动物编号Animal

   MinDist=INFINITY;

   for( i=0;i<Graph->Mv;i++){

       MaxDist=FindMaxDist(D,i,Graph->Nv);//找到第i个动物它的最大的那个距离赋给MaxDist这个变量

   

   //还有一个特殊情况需要考虑:带一只动物去根本不可能,当图不连通的时候,图有不止一个连通集。该从哪里意识到图不连通了呢?

       if(MaxDist==INFINITY){//返回距离无穷大的话说明有i无法变出的动物

           printf("0\n");

           return;

       }

       

       

       if( MinDist>MaxDist ){//找到最长距离更小的动物

           MinDist=MaxDist; Animal=i+1;//更新距离,记录编号。这里是i+1是因为动物编号从1开始,但是图的循环从0开始,所有需要加一

       }

   }      

   printf("%d %d\n",Animal,MinDist);

}

上述代码中涉及到封装起来的函数

WeightTypeFindMaxDist(WeightTypeD[][MaxVertexNum],Vertexi,intN)

{

   WeightTypeMaxDist;

   Vertexj;

   

   MaxDist=O;//初始化为一个很小的数,比如0

   for(j=0;j<N;j++ )//找出i到其他动物j的最长距离

       if( i!=j&&D[i][j]>MaxDist )//邻接矩阵所有的两个顶点之间的距离全部初始化为正无穷,所以对角元的值永远是正无穷。所以必须要把对角元排除掉跳过去,不排除的话这个无穷大必然会符合这个判断条件从而让MaxDist永远的返回正无穷

           MaxDist=[i][j];

   returnMaxDist;

}

小白-HP.4 模块的引用与裁剪

网络异常,图片无法展示
|

#define MaxVertexNum 100//最大顶点数设置为100

#define INFINITY 65535//无穷大设为双字节无符号整数的最大值65535

typedefintVertex//用顶点下标表示顶点,为整型

typedefintWeightType;//边的权值设为整型

//边的定义

typedefstructENode*PtrToENode;

structENode{

   VertexV1,V2;//有向边<V1,V2>

   WeightTypeWeight;//权重

};

typedefPtrToENodeEdge;

//图结点的定义

typedefstructGNode*PtrToENode;

structGNode{

   intNv;//顶点数

   intNe;//边数

   WeightTypeG[MaxVertexNum][MaxVertexNum];//邻接矩阵

   DataTypeData[MaxVertexNum];//存顶点的数据

   //注意:很多情况下,顶点无数据,此时Data[]可以不出现

};

typedefPtrToENodeMGraph;//以邻接矩阵存储的图类型

CreateGraph原始代码

MGraphCreateGraph(intVertexNum)

{/*初始化一个有VertexNum个顶点但没有边的图*/

   VertexV,W;

   MGraphGraph;

   

   Graph=(MGraph)malloc(sizeof(structGNode));/*建立图*/

   Graph->NvVertexNum;

   Graph->Ne=0;

/*初始化邻接矩阵*/

/*注意:这里默认顶点编号从0开始,到(Graph->Nv-1)*/

for (V=0; V<Graph->Nv; V++)

   for (W=0; W<Graph->Nv; W++)

       Graph->G[V][W] =INFINITY;

   returnGraph;

}

voidInsertEdge(MGraphGraph,EdgeE)

{

/*插入边<V1,V2>*/

   Graph->G[E->V1][E->V2] =E->Weight;

/*若是无向图,还要插入边<V2,V1>   因为是无向图,所以我们需要把读进来的这个权重同时赋予矩阵里面两个元素*/

   Graph->G[E->V2][E->V1] =E->Weight;

MGraphBuildGraph()

{

   MGraphGraph;

   EdgeE;

   VertexV;

   intNv,i;

   

   scanf("%d",&Nv);//读入顶点个数

   Graph=CreateGraph(Nv);//初始化有Nv个顶点但没有边的图

   

   scanf("%d",&(Graph->Ne));//读入边数

   if(Graph->Ne!=0 ){//如果有边

       E= (Edge)malloc(sizeof(structENode));//建立边结点

       //读入边,格式为"起点 终点 权重",插入邻接矩阵

       for(i=0;i<Graph->Ne;i++){

           scanf("%d %d %d",&E->V1,&E->V2&E->Weight);//读进来的时候,编号是从1开始的

           //注意:;如果权重不是整型,Weight的读入格式要改

           E->V1--; E->V2--;//读进来的编号都-1,那就变成起始编号从0开始的了,原本1变成0,2变成1,依次变化

           InsertEdge(Graph,E);//插入边的时候,图默认顶点的编号是从0开始

       }

   }

   //如果顶点有数据的话,读入数据。没有的话这个for循环可以删掉

   for(V=0;V<Graph->Nv;V++)

       scanf(" %c",$(Graph->Data[V]));

   

   returnGraph;

}

问:图的顶点从0开始编号,而本题目中动物从1开始编号。读输入时该如何处理使得图的相关模块可以顺利应用?

答案:E->V1--; E->V2--;

标准的Floyd算法

boolFloyd(MGraphGraph ,WeightTypeD[][MaxVertexNum],Vertexpath[][MaxVertexNum])//返回布尔值(bool)

{

   Vertexi,j,k;

   //初始化

   for(i=0;i<Graph->Nv;i++)

       for(j=0;j<Graph->Nv;j++){

           D[i][j] =Graph->G[i][j];

           path[i][j] =-1;

       }

   

   for(k=0;k<Graph->Nv;k++)

       for(i=0;i<Graph->Nv;i++)

           for(j=0;j<Graph->Nv;j++)

               if(D[i][k] +D[k][j] <D[i][j]){

                   D[i][j] =D[i][k] +D[k][j];

                   if( i==j&&D[i][j]<0)//若发现负值圈,从i出发,走了一圈又回到i,这个最短距离是一个负的值,也对应了一个负值圈

                       returnfalse;//不能正确解决,返回错误标记

                   path[i][j] =k;

               }

   returntrue;//算法执行完毕,返回正确标记

}

在本题中进行的改动部分:

网络异常,图片无法展示
|

目录
相关文章
|
6月前
|
存储 算法
数据结构===图
数据结构===图
|
5月前
|
算法 Python
逆袭之路!用 Python 玩转图的 DFS 与 BFS,让数据结构难题无处遁形
【7月更文挑战第12天】图的遍历利器:DFS 和 BFS。Python 中,图可表示为邻接表或矩阵。DFS 沿路径深入,回溯时遍历所有可达顶点,适合找路径和环。BFS 层次遍历,先近后远,解决最短路径问题。两者在迷宫、网络路由等场景各显神通。通过练习,掌握这些算法,图处理将游刃有余。
67 3
|
5月前
|
存储 算法 Python
“解锁Python高级数据结构新姿势:图的表示与遍历,让你的算法思维跃升新高度
【7月更文挑战第13天】Python中的图数据结构用于表示复杂关系,通过节点和边连接。常见的表示方法是邻接矩阵(适合稠密图)和邻接表(适合稀疏图)。图遍历包括DFS(深度优先搜索)和BFS(广度优先搜索):DFS深入探索分支,BFS逐层访问邻居。掌握这些技巧对优化算法和解决实际问题至关重要。**
51 1
|
6月前
|
存储 算法
【单向链表】数据结构——单向链表的介绍与代码实现&笔记
【单向链表】数据结构——单向链表的介绍与代码实现&笔记
|
6月前
|
存储 算法
【树】数据结构——树和二叉树的概念&笔记
【树】数据结构——树和二叉树的概念&笔记
|
6月前
|
算法 Java 索引
12.12_黑马数据结构与算法笔记Java
12.12_黑马数据结构与算法笔记Java
52 1
|
5月前
|
存储 算法 C语言
软考中级之数据库系统工程师笔记总结(二)数据结构与算法
软考中级之数据库系统工程师笔记总结(二)数据结构与算法
41 0
|
6月前
|
存储 算法 Linux
【内核链表】数据结构——深入理解内核链表的概念和操作&笔记
【内核链表】数据结构——深入理解内核链表的概念和操作&笔记
【循环链表】数据结构——单向循环链表和双向循环链表操作&笔记
【循环链表】数据结构——单向循环链表和双向循环链表操作&笔记
|
6月前
|
存储
数据结构学习记录——如何建立图(邻接矩阵、邻接表-图节点的结构、创建并初始化、插入变、完整图的建立)
数据结构学习记录——如何建立图(邻接矩阵、邻接表-图节点的结构、创建并初始化、插入变、完整图的建立)
97 0