数据结构8 Graph

定义

不能有自环,无向图任意两个顶点之间不能有两条边

Complete graph:完全图,拥有最大的边数

无向图 E=C(V,2)

有向图 E=2C(V,2)

connected:联通,任意两个顶点都有一条路径相连。

Strongly connected:强联通,对于有向图,任意两个顶点必须有路径使得v->w,w->v

边数最小的联通图是树,E=V-1

Simple path:路径中的点是不同的。

Connected Component:联通分量,即一个图中联通的部分。

degree:度数,一个顶点连接的边数

图的实现

图的实现只需要记录下所有的点的连接情况或者所有的边即可

二维数组(即邻接矩阵)

Graph[a][b] = 1

对于无向图说明a与b相连

对于有向图说明a->b

Graph[a][b] = 0

a,b不联通

显然无向图的矩阵是对称的。

计算v的度数:

无向图: ∑ i = 0 v − 1 G r a p h [ v − 1 ] [ i ] \sum\limits_{i=0}^{v-1}Graph[v-1][i] i=0v1Graph[v1][i]
有向图: ∑ i = 0 v − 1 G r a p h [ v − 1 ] [ i ] + ∑ i = 0 v − 1 G r a p h [ i ] [ v − 1 ] \sum\limits_{i=0}^{v-1}Graph[v-1][i]+\sum\limits_{i=0}^{v-1}Graph[i][v-1] i=0v1Graph[v1][i]+i=0v1Graph[i][v1]

对于点的存储方式:索引到底要不要加1,只要自己约定好就可以。

记录带权图:将1改为权重

数组+链表

对于每一个点v,Graph[v]是链表的头

链表的每个元素记录下与其相连的点

计算点的度数:即链表的结点数。(第一个结点不算)

往往会这样实现:

typedef struct AdjVNode *PtrToAdjVNode; 
struct AdjVNode{/*一个顶点结点*/
    Vertex AdjV;
    PtrToAdjVNode Next;
};

typedef struct Vnode{
    PtrToAdjVNode FirstEdge;
} AdjList[MaxVertexNum];/*图的数组,指向第一个顶点*/

typedef struct GNode *PtrToGNode;
struct GNode{  
    int Nv;
    int Ne;
    AdjList G;
};/*一个图的结点,记录边的个数,点的个数,以及数组*/
typedef PtrToGNode LGraph;

另一种方法是结点记录边:

结点的中记录边的两个点,以及该点的下一条边结点

typedef struct AdjENode{
	Vertex Adjv;
	PtrToAdjENode vNext;
	Vertex Adjw;
	PtrToAdjENode wNext;
};

在这里插入图片描述

拓扑排序

是一张图所有点的排序。如果两个点之间可能存在顺序a>b,也可能不存在顺序。拓扑排序就是将点按顺序进行排列,只需满足具有的顺序即可。

因此同一张图可能具有多个拓扑序。

比如一张图中有a,b,c三个点,a->b,c->b,则a,c,b和c,a,b都是拓扑序

思路是最前面的点必须满足入度为0,因此先找到一个入度为0的点,将它加入序列,再去掉该点,即将所有和它相邻的点入度减少1。再次循环。

实现:

void Topsort( Graph G )
{   int  Counter;
    Vertex  V, W;
    for ( Counter = 0; Counter < NumVertex; Counter ++ ) {
		V = FindNewVertexOfDegreeZero( );
		if ( V == NotAVertex ) {
	    	Error ( “Graph has a cycle” );   
	    	break;  
		}
		TopNum[ V ] = Counter; /* or output V */
		for ( each W adjacent to V )
	    	Indegree[ W ] – – ;
    }
}

复杂度O(V^2)

上面的方法减少入度以后都需要重新再找入度为0的点,很显然在减少以后判断是否为0,如果是的话可以入队列。不需要下次再从头找一次了。

下面的算法思路是首先所有度数为0的入队列,然后一个点出队列,将与它相邻的点度数减1,如果度数为0,入队列。这样操作直到队列空为止。

void Topsort( Graph G )
{   Queue  Q;
    int  Counter = 0;
    Vertex  V, W;
    Q = CreateQueue( NumVertex );  MakeEmpty( Q );
    for ( each vertex V )
		if ( Indegree[ V ] == 0 )   Enqueue( V, Q );
    while ( !IsEmpty( Q ) ) {
		V = Dequeue( Q );
		TopNum[ V ] = ++ Counter; /* assign next */
		for ( each W adjacent to V )
	   	 	if ( – – Indegree[ W ] == 0 )  Enqueue( W, Q );
    }  /* end-while */
    if ( Counter != NumVertex )
		Error( “Graph has a cycle” );
    DisposeQueue( Q ); /* free memory */
}

复杂度O(V+E)

题目

1.In a connected graph, the number of edges must be greater than the number of vertices minus 1.

最小的情况是E=v-1,即树

2.In a directed graph, the sum of the in-degrees must be equal to the sum of the out-degrees of all the vertices.

入度和出度对应一条边的起始和结束,如果出入度不相等说明有一条边只和一个顶点相连。

3.If graph G is NOT connected and has 35 edges, then it must have at least ____ vertices.

因为C(9,2)=36,即9个顶点的连通图最多有36条边,35条边也能符合。C(8,2)=28,即8个顶点的联通图最多有28条边,显然是达不到35条边的,因此如果是不连通的,必须加上一个独立的顶点,9 + 1 = 10

4.A graph with 90 vertices and 20 edges must have at least __ connected component(s).

根据欧拉公式,对于一个联通图 r=v-e+2,r是区域的数量。将一个图的一个联通分量看作一个联通图,假如有k个联通分量,求和可以得到,R=V-E+2k。但是注意到所有联通分量中最外部的那个区域被计算了k次,其实只需计算一次,因此需要减掉。R=V-E+2k-(k-1)=V-E+k+1
这就是任意图都能使用的欧拉公式。
代入可得:k=R+69,为了让联通分量最小,取R=1,即k=70

5.Given an undirected graph G with 16 edges, where 3 vertices are of degree 4, 4 vertices are of degree 3, and all the other vertices are of degrees less than 3. Then G must have at least __ vertices.

根据2e=sum(degree),32=12+12+d*(v-7),其中d<3,因此8<=2(v-7),v>=11

  • 4
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值