数据结构——图

重点难点在于最小生成树的两种算法以及最短路径的算法

最小生成树:
Prime 和 Kruskal
最小生成树的Kruskal算法是一个贪心法。(T)

图的存储结构
Kruskal 算法是通过每步添加一条边及其相连的顶点到一棵树,从而逐步生成最小生成树。 (F)
解析:
prim算法是通过每步添加一条边及其相连的顶点到一棵树,从而逐步生成最小生成树;
Kruskal 算法是维护一个森林,每一步把两棵树合并成一棵;

用一维数组G[]存储有4个顶点的无向图如下:G[] = { 0, 1, 0, 1, 1, 0, 0, 0, 1, 0 },则顶点2和顶点0之间是有边的。(T)
在这里插入图片描述
在一个有向图中,所有顶点的入度与出度之和等于所有边之和的2倍。(T)

求邻接矩阵存储结构的有向图G中各顶点的入度

  1. 什么是出度与入度?
    在有向图中,箭头是具有方向的,从一个顶点指向另一个顶点,这样一来,每个顶点被指向的箭头个数,就是它的入度。从这个顶点指出去的箭头个数,就是它的出度
  2. 怎样计算一个顶点的入度与出度
    邻接矩阵的行号即代表箭头的出发结点,列号是箭头的指向结点,所以矩阵中同一行为1的表示有从第i个结点指向第j个结点这样一条边,而在同列为1就代表第j个结点被第i个结点指向,因此要求顶点的出度与入度,只需要判断同列为1的个数,同行为1的个数

用邻接矩阵法存储图,占用的存储空间数只与图中结点个数有关,而与边数无关。(T)

邻接矩阵法的存储大小为n2,只与顶点数有关,与边无关
邻接矩阵存储方式是用2个数组来表示图,一维数组存顶点信息,边存储就是用一个二维数组存储,有n个顶点,二维数组就至少得有n2个存储空间来存储
课本P154:用邻接矩阵表示法表示图,除了一个用于存储邻接矩阵的二维数组外,还需要一个一维数组来存储顶点信息;

用邻接表法存储图,占用的存储空间数只与图中结点个数有关,而与边数无关。(F)

邻接矩阵的空间复杂度为O(n 2 ),与边的个数无关。
邻接表的空间复杂度为O(n + e ),与图中的结点个数和边的个数都有关。

如果无向图G必须进行两次广度优先搜索才能访问其所有顶点,则G一定有2个连通分量。 (T)

解析:
进行一次广度优先搜索,则与之连通的结点都会遍历到。

图的深度优先遍历非递归算法通常采用栈实现,广度优先遍历非递归算法通常采用队列实现。(T)

图的深度优先遍历非递归C语言实现(邻接矩阵、邻接表)

无向连通图所有顶点的度之和为偶数。 (T)

解析:
无向图定义:
任何两个节点之前都是连通的,都存在一条路径,并且图中没有方向。
结论:
顶点的度为顶点所连接的边的个数,无向连通图中的顶点的度之和为边数*2所以顶点的度之和为偶数

如果无向图G必须进行两次广度优先搜索才能访问其所有顶点,则G一定有2个连通分量。(T)

连通分量:无向图G的极大连通子图称为G的连通分量( Connected Component)。任何连通图的连通分量只有一个,即是其自身,非连通的无向图有多个连通分量。

若图G为连通图,则G必有唯一的一棵最小生成树。(F)

如果是连通图,那么一定有最小生成树,但不一定唯一,如果有多条权值一样的路,就不唯一了

无向图中的一条边,在其邻接表存储结构中对应两个弧结点。()

弧:<v,w>表示从v到w的一条弧,v为弧尾,w为弧头。

无向连通图边数一定大于顶点个数减1。 (F)

解析:
以两个结点的图为例,此图为连通图,边数为1,顶点数为2;边数一定没有大于顶点个数减1;

具有5个顶点的有向完全图有多少条弧?(20)

因为在有向完全图中,任何两个顶点之间都有2条弧所以在n个顶点中选取两个顶点的选法有n(n-1)/2所以共有2*n(n-1)/2=n(n-1)条弧

下面给出的有向图中,有__个强连通分量。
在这里插入图片描述

2 个 ({1,2,3,4}, {0})
强连通分量

使用迪杰斯特拉(Dijkstra)算法求下图中从顶点1到其他各顶点的最短路径,依次得到的各最短路径的目标顶点是:
在这里插入图片描述

5, 2, 3, 6, 4
对于dijkstra算法来说,只有当一个点的所有入度都被遍历过之后,才能完全确认起点到这个点的距离。但这道题没有那么严谨,它的意思似乎仅仅是给各最短路径排序,从短到长。

在这里插入图片描述

在这里插入图片描述
使用迪杰斯特拉(Dijkstra)算法求下图中从顶点1到其他各顶点的最短路径,依次得到的各最短路径的目标顶点是:
在这里插入图片描述

6, 7, 5, 3, 2, 4

给定一个图的邻接矩阵如下,则从V1出发的深度优先遍历序列(DFS,有多种选择时小标号优先)是:
在这里插入图片描述

****如果无向图G必须进行两次广度优先搜索才能访问其所有顶点,则G中一定有回路。(F)

???

无向图中的一条边,在其邻接表存储结构中对应两个弧结点。(T)

???

最小生成树的Kruskal算法是一个贪心法。

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

(1分)

函数题:
6-1 邻接矩阵存储图的深度优先遍历 (10 分)
试实现邻接矩阵存储图的深度优先遍历。
函数接口定义:

void DFS( MGraph Graph, Vertex V, void (*Visit)(Vertex) );

其中MGraph是邻接矩阵存储的图,定义如下:

typedef struct GNode PtrToGNode;
struct GNode{
int Nv; /
顶点数 /
int Ne; /
边数 /
WeightType G[MaxVertexNum][MaxVertexNum]; /
邻接矩阵 /
};
typedef PtrToGNode MGraph; /
以邻接矩阵存储的图类型 */
函数DFS应从第V个顶点出发递归地深度优先遍历图Graph,遍历时用裁判定义的函数Visit访问每个顶点。当访问邻接点时,要求按序号递增的顺序。题目保证V是图中的合法顶点。

裁判测试程序样例:

#include <stdio.h>

typedef enum {false, true} bool;
#define MaxVertexNum 10  /* 最大顶点数设为10 */
#define INFINITY 65535   /* ∞设为双字节无符号整数的最大值65535*/
typedef int Vertex;      /* 用顶点下标表示顶点,为整型 */
typedef int WeightType;  /* 边的权值设为整型 */

typedef struct GNode *PtrToGNode;
struct GNode{
    int Nv;  /* 顶点数 */
    int Ne;  /* 边数   */
    WeightType G[MaxVertexNum][MaxVertexNum]; /* 邻接矩阵 */
};
typedef PtrToGNode MGraph; /* 以邻接矩阵存储的图类型 */
bool Visited[MaxVertexNum]; /* 顶点的访问标记 */

MGraph CreateGraph(); /* 创建图并且将Visited初始化为false;裁判实现,细节不表 */

void Visit( Vertex V )
{
    printf(" %d", V);
}

void DFS( MGraph Graph, Vertex V, void (*Visit)(Vertex) );

int main()
{
    MGraph G;
    Vertex V;
    G = CreateGraph();
    scanf("%d", &V);
    printf("DFS from %d:", V);
    DFS(G, V, Visit);
    return 0;
}

输入样例:给定图如下

5

输出样例:

DFS from 5: 5 1 3 0 2 4 6
结尾无空行

  void DFS( MGraph Graph, Vertex v, void (*Visit)(Vertex) )
{
    Visited[v]=true;
    Visit(v);
    for(int i=0; i<Graph->Nv; i++)
    {
        if(Graph->G[v][i]==1&&!Visited[i])
        {
            DFS(Graph,i,Visit);
        }
    }
}

void DFS( MGraph Graph, Vertex V, void (*Visit)(Vertex) )
{
    Visit(V);
    Visited[V] = true;
    for(int i = 0; i < (*Graph).Nv; i ++ )
        if((*Graph).G[V][i] == 1 && Visited[i] == false)
            DFS(Graph,i,Visit);
}

在这里插入图片描述

Visit函数用来输出访问的结点
Visited数组 -> 标记数组,表示该顶点是否访问过
注意Graph-> ???

创建图的函数:

MGraph CreateGraph()
{
    int Nv, i, VertexNum;
    int v1, v2;
    Vertex V, W ;
    MGraph Graph;
    scanf("%d", &VertexNum);
    Graph = (MGraph)malloc(sizeof(struct GNode));
    Graph->Nv = VertexNum;
    Graph->Ne = 0;
    for(V = 0; V < Graph->Nv; V ++)
    {
        for(W = 0; W < Graph->Nv; W ++)
        {
            Graph->G[V][W] = INFINITY;
        }
    }
    scanf("%d", &Graph->Ne);
    if(Graph->Ne)
    {
        for(i = 0; i < Graph->Ne; i ++)
        {
            scanf("%d %d", &v1, &v2);
            Graph->G[v1][v2] = 1;
            Graph->G[v2][v1] = 1;
        }
    }
    return Graph;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值