zoukankan      html  css  js  c++  java
  • DS博客作业04——图

    0.PTA得分截图

    1.本周学习总结

    图存储结构

    邻接矩阵

    • 简单来讲使用二维数组进行存储,设位edge[M][N]。其中,M,N代表两个顶点,edge[M][N]可代表是否连通或者权值。
      邻接矩阵的特点:

    • 若图为无向图,则矩阵是沿对角线是对称的。
      可以直接访问顶点M,N间边的关系以及权值。
      缺点:

    • 存储的图为稀疏图时,浪费的空间较多,n个顶点所需空间至少为n^2。
      结构体定义

    typedef struct //图的定义
    { int edges[MAXV][MAXV]; //邻接矩阵
    int n,e; //顶点数,边数
    } MGraph;

    • 邻接表
      采用结构体数组跟链表结合,存储每个顶点的临边
      特点:

    • 存储的图为无向图时,遍历顶点数组每个临边即可遍历整张图
      相比于邻接矩阵更节省空间
      缺点

    • 无法直接知道任一两个顶点之间的关系。
      存储的图为有向图时,同一条边会生成两条链。

    定义如下

    typedef struct ANode
    {  
        int adjvex;			//该边的终点编号
        struct ANode *nextarc;	//指向下一条边的指针
        int info;	                //该边的相关信息,如权重
    } ArcNode;			//边表节点类型
    typedef int Vertex;
    typedef struct Vnode
    {  
        Vertex data;		//顶点信息
        ArcNode *firstarc;		//指向第一条边
    } VNode;			//邻接表头节点类型
    typedef VNode AdjList[MAXV];    //头结点数组
    typedef struct 
    {  
        AdjList adjlist;	        //邻接表
        int n,e;		        //图中顶点数n和边数e
    } AdjGraph;	
    

    图遍历及应用

    • 首先要了解图遍历,就要先清楚:什么是图遍历
      从给定的图中任意一个顶点开始,按照某种搜索方法(DFS、BFS)沿着图的边访问图中的所有顶点,并且要注意,每个顶点只能被访问一次,,这个过程就叫做图遍历。
    • 图的遍历相对于树的遍历来说更加复杂,因为对于树来说,从树的根部到树中任意几点只有唯一的一条路径,但是,对于图来说,从图的初始点到图的任意一个顶点,大概率都会存在多条路径,即当沿着图中的一条路径访问过某一顶点后,还可能会沿着另一条路径回到初始顶点,也就是我们说的回路。所以为了避免同一个顶点被访问多次,就引入了一个访问标记数组visited,若顶点被访问过则将visited的值置为1,否则置为0.

    深度优先遍历

    • 深度优先遍历的过程是从图中的某个点v出发,然后选择一个与顶点v相邻且没有被访问过的顶点w,然后再以w为顶点,重复上述操作,直到所有顶点都被访问为止。(采用递归的方法)
    int visited[MAX]={0};
    
    //全局数组
    
    void DFS(AdjGraph * G,int v)
    
    //深度优先遍历算法
    
    ArcNode * p;
    
    visited[v]=1;
    
    //置已访问标记
    
    printf("%d ",v);
    
    //输出被访问顶点的编号
    
    p=G-> adjlist[v]. firstarc;
    
    //p指向顶点v的第一个邻接点
    
    while (p!= NULL)
    
    { if (visited[p-> adjvex]==0) //若p-> adjvex顶点未被访问, 递归访问它
    
    DFS(G,p-> adjvex);
    
    P=P- > nextarc;
    
    //p指向顶点v的下一个邻接点
    
    }
    

    广度优先遍历

    广度优先遍历和深度优先遍历稍有不同,广度优先遍历的过程是首先访问初始点v,接着访问v的所有未被访问过的邻接点,v1,v2,v3....,访问完毕后再按照v1,v2,v3...,的顺序访问所有顶点每一个未被访问过的邻接点,以此类推,直到图中所有顶点都被访问过一次为止。

    void BFS( AdjGraph*G, int v)
    
    int w, i;ArcNode*p;
    
    //定义环形队列指针
    
    SqQueue*qu;
    
    InitQueue(qu);
    
    //初始化队列
    
    int visited[MAXV];
    
    //定义顶点访问标记数组
    
    for (i=0;i<G-> n;i++) visited[i]=0;
    
    //访问标记数组初始化
    
    printf("%2d",v);
    
    //输出被访问顶点的编号
    
    visited[v]=1;
    
    //置已访问标记
    
    enQueue(qu, v);
    
    while (!QueueEmpty(qu))
    
    //队不空循环
    
    { deQueue(qu, w);
    
    //出队一个顶点w
    

    非连通图

    对于无向图来说,若是连通图,则一次遍历就能访问到所有的节点,但是如果无向图是非连通图,则只能访问到初始点所在的连通分量中的所有顶点,其他连通分量中的顶点是不能访问到的,所有要再次从其他的连通分量中寻找初始点再次进行遍历,这样才能访问到图中的所有顶点
    采用深度优先遍历非连通图无向图的算法如下:

    DFS1(AdjGraph * G)
    
    int i;
    
    for (i=0;i<G-> n;i++ )
    
    if (visited[i]==0) DFS(G,i);
    

    采用广度优先遍历非连通图无向图的算法如下:

    BFSI(AdjGraph *G)
    
    int 1;
    
    for (i=0;i<G-> n;i十十)
    
    if (visitedli」==0) BFS(G,i);
    

    判断无向图是否连通

    bool Connect(AdjGraph *G)
    
    //判断无向图G的连通性
    
    (int i;
    
    bool flag= true;
    
    for (i=0;i<G->n;i++)
    
    //visited数组置初值
    
    visited[i]=0;
    
    DFS(G, 0);
    
    //调用前面的中DSF算法,从顶点0开始深度优先遍历
    
    for (i=0;i<G-> n;i十十)if (visited[i]==0)
    
    //若有顶点没有被访问到,说明是不连通的
    
    flag= false;
    
    break;
    
    return flag;
    

    查找顶点间是否存在简单路径

    即再深度遍历的基础上增加两个形参,其中一个判断两顶点间是否有路径,若有则返回true

    void ExistPath( AdjGraph *G, int u,int v,bool &.has){ //has表示u到v是否有路径,初值为false
    
    int w; ArcNode * p;
    
    visited[u]=1;
    
    //置已访问标记
    
    if (u==v)
    
    //找到了一条路径
    
    has= true;
    
    //置has为true并返回
    
    return ;
    
    p=G- -> adjlist[u]. firstarc;
    
    //p指向顶点u的第一个邻接点
    
    while (p!= NULL)
    
    w=p- > adjvex;
    
    //w为顶点u的邻接点
    
    if (visited[w]==0)
    
    //若w顶点未访问,递归访问它
    
    ExistPath(G, w,v, has);
    
    P=p- > nextarc;
    
    //p指向顶点u的下一个邻接点
    
    }
    

    输出一条两顶点之间的简单路径

    void FindaPath(AdjiGraph *G,intu,int v,intpathC],int dy(//d表示path中的路径长度,初始为-1
    
    int w,i;ArcNode* p;
    
    visited[u]= 1;
    
    d++; path[d]=u;
    
    //路径长度d增1.顶点0加人到路径中
    
    if (u==v)
    
    ( for (i=0;i<=d;i++)
    
    //找到一条路径后输出并返回
    
    printf("%d ",path[i);
    
    printf("
    ");
    
    return ;
    
    p=G - > adjlist[u]. firstarc;
    
    //p指向顶点u的第一个邻接点
    
    while (p!= NULL)
    
    {w=p - -> adjvex;
    
    //邻接点的编号为w
    
    if (visited[w]==0)
    
    FindaPath( G, w, V, path,d);p=p - > nextarc;
    
    //p指向顶点u的下一个邻接点
    
    }
    

    寻找两顶点间的最短路径

    • 即求距离顶点u到顶点v的边数最少的顶点序列。利用广度优先遍历算法,从u出发一层一层的向外拓展
      结构体定义如下:
    typedef struct{int data;
    
    //顶点编号
    
    1nt parent;
    
    //前一个顶点的位置
    
    } QUERE;
    
    //非环形队列类型
    
    void FindaPath AdjGraph* G, int
    
    ( //d表示 path中的路径长度,u,int v,intpathC].int d
    
    int w,i;ArcNode *P;
    
    初始为一1
    
    visited[u]=1;
    
    d++; path[d]=u;
    
    /路径长度d增1.顶点0加人河路径中
    
    if (u==v)
    
    { for (i=0;i<=d:i+H //找到一 条路径后输 出并返回
    
    printf("%d”.,path[i]);
    
    printf("
    ");
    
    return;
    
    }
    
    p=G -> adjlist[u] . firstare;
    
    //p指向顶点u的第一个邻接点
    
    while (p!= NULL)
    
    w=p- > adjvex;
    
    //邻接点的编号为w
    
    if (visited[w]==0)
    
    FindaPath( G, w, v, path,d);
    
    p=p- > nextarc;
    
    //p指向顶点u的下一个邻接点
    
    }
    
    }
    while (p!= NULL)
    
    { if (visited[p-> adjvex]==0)
    
    {visited[p-> adjvex]=1;
    
    rear++ ;
    
    //将w的未访问过的邻接点进队
    
    qu[ rear].data=p- > adjvex;
    
    qu[ rear」. parent= front;
    
    p=P一> nextarc;
    
    //找w的下一个邻接点
    

    最小生成树

    • 生成树:一个连通图的生成树是一个极小

    图存储结构

    最小生成树相关算法及应用
    最短路径相关算法及应用,可适当拓展最短路径算法
    拓扑排序、关键路径
    上面要求是必须完成,但是完成时候需要根据实际所学再展开。内容简单应付,0分。注意每个知识点务必要举例,图形等说明。

    这块内容是总结复习,所有操作、代码清自己写代码或伪代码演示,不得复制课件代码或PPT

    1.2.谈谈你对图的认识及学习体会。
    本块内容必须用自己语言总结所学及图的相关应用。

    2.阅读代码(0--5分)
    找3份优秀代码,理解代码功能,并讲出你所选代码优点及可以学习地方。主要找以下类型代码:

    考研题
    PAT天梯赛题目
    ACM题解
    leecode--图1
    leecode--图2
    题目集可能有和图无关题目,但是阅读代码必须选择和图相关题目
    注意:不能选教师布置在PTA的题目。完成内容如下。

    2.1 题目及解题代码
    可截图,或复制代码,需要用代码符号渲染。题目截图后一定要清晰。

    2.1.1 该题的设计思路
    链表题目,请用图形方式展示解决方法。同时分析该题的算法时间复杂度和空间复杂度。

    2.1.2 该题的伪代码
    文字+代码简要介绍本题思路

    2.1.3 运行结果
    网上题解给的答案不一定能跑,请把代码复制自己运行完成,并截图。

    2.1.4分析该题目解题优势及难点

  • 相关阅读:
    简单的分页存储过程,Json格式日期转换为一般日期
    事件的那些事
    关于1Byte 1K 1M 1G(换算)
    VS自带WCF测试客户端简单介绍
    “System.Transactions.Diagnostics.DiagnosticTrace”的类型初始值设定项引发异常[WCF]
    周末大放送网站图片上传,水印,预览,截图
    FIREDAC驱动ORACLE的配置
    匿名方法实现多线程同步到主线程执行
    DELPHI跨平台的临界替代者
    三层数据库设计注意事项
  • 原文地址:https://www.cnblogs.com/lmh123/p/12833226.html
Copyright © 2011-2022 走看看