Graph Algorithm

1、定义

A graph consists of a set of vertices V and a set of edges E.

Each edge is a pair (v, w), where v,w belong to V.

路径 A path in a graph is a sequence of vertices w1, w2, ... ,wn.

长度 The length of such a path is the number of edges on the path, which is equal to N-1.

权 Sometimes an edge has a third component, known as either a weight or a cost.

Spanning tree 生成树

假设一个连通图有N 个顶点和e条边,其中n-1 条边和n个顶点构成一个极小连通子图,称该极小连通子图为此树的生成树

2、图的储存表示

1)邻接矩阵表示法

顶点表:记录各个顶点信息的一位数组

邻接矩阵:一个表示各个顶点之间的关系(边或弧)的二维数组。

const MAX_NUM=20;   //最大顶点数
typedef int AdjMatrix[MAX_NUM][MAX_NUM];  //邻接矩阵

typedef struct
{
	VertexType vexs[MAX_NUM]; //顶点表
	AdjMatrix arcs;  //邻接矩阵
	int vexnum, arcnum; //图实际顶点数与弧数
}MGraph;

在无向图中,第i行(列)1的个数就是顶点i的度。

无向图的邻接矩阵是对称的;

有向图的邻接矩阵可能是不对称的。

在有向图中,第i行1的个数就是顶点i的出度,第j列1的个数就是j的入度

如果有权值的存在,则也可以在邻接矩阵上加上

2)邻接表

以一种链式结构形式的存储结构

typedef struct ArcNode
{
	int ajdvex; //该弧所指向结点的位置
    ArcNode* nextArc;  //指向下一条弧指针
    InfoNode info;  //弧所带信息,可以是权值
}ArcNode;

typedef struct VNode
{
    VertexType data; //顶点信息
    ArcNode* firstArc;  //指向第一条依附该结点的弧的位置
}VNode, Adjist[MAX_NUM][MAX_NUM];

typedef struct
{
	Adjist verties;  //邻接表
	int vexnum, arcnum;
	int kind; //图的种类
}ALgraph;

  

带权图的边结点中info保存改变上的权值。

顶点Vi的边链表的头结点存放在下标为i的顶点数组中。

在邻接表的边链表中,各个边结点的链入顺序任意,视边结点输入次序而定。

设图中有n个结点,e条边,则用邻接表表示无向图时,需要n个顶点结点,2*e个边结点;

用邻接表表示有向图时,若不考虑你邻接表,只需n个顶点结点,e个边结点。

建立邻接表的时间复杂度为O(n*e),若顶点信息为顶点的下标,则时间复杂度为O(n+e).

3、图的遍历

从图的某一个顶点出发访问遍图中其余顶点,且使每个顶点仅被访问过一次,就叫做图的遍历。

为避免重复访问,可设置一个表示顶点是否被访问过的辅助数组visited[],它的初始状态设置为0,一旦某个结点被访问过则立即让对应的visited[i]=1

1)DFS 深度优先搜索

算法思想:

从图的某一结点v开始,由v出发,访问它的任一邻接顶点w1;再从w1出发,访问与w1邻接但还没有访问过的顶点w2;再从w2出发,进行类似的访问,…… 如此进行下去,直至到达所有的邻接顶点都被访问过的顶点u为止。接着,退回一步,退到前一次刚访问过的顶点,看是否还有其他没有访问过的邻接顶点。如果有,则访问此顶点,之后再从此顶点出发,进行与上述类似的访问;如果没有,就在退回一步进行搜索,重复上述过程,直到连通图中所有顶点都被访问过为止。(贪心算法?)

进一步描述:

(1)从图中某个顶点v出发,访问之;

(2)依次从顶点v的未被访问过的邻接点出发,深度优先遍历图,直到图中所有和顶点v有路径相同的顶点都被访问到;

(3)若此时图中尚有顶点未被访问到,则另选一个未被访问过的顶点作起始点,重复上述(1)(2)的操作,直到图中所哟的顶点都被访问到为止。

//DFS
//遍历算法
void Graph_Traverse(AdjGraph G)
{
	int* visited = new int[NumVertices];
	for(int i=0; i<G.n;i++)
		visiter[i]=0; //访问数组visited初始化
	for(int i=0;i<G.n;i++)
		if(!visited[i])DFS(G, i, visited);

	delete[] visited;
}

void DFS(AdjGraph G, int v, int visited[])
{
	cout<<GetValue(G,v)<<" "<<endl; //访问顶点v
    visited[v]=1;
    int w=GetFirstNeighbor(G,v); //取v的第一个邻接顶点w
    while(w!=-1)
    {
    	if(!visited[w])DFS(G,w,visited);  //若顶点w未访问过,递归访问顶点w
    	w=GetNextNeighbor(G,v,w);  //取顶点v排在w后下一个邻接顶点
    }
}

  

图中有n个顶点,e条边。

如果用邻接表表示图,沿Firstarc->nextarc 链可以找到某个顶点v 的所有邻接顶点w。由于总共有2e个边结点,所以扫描边的时间为O(e),而且对所有顶点递归访问1次,时间复杂度为O(n+e)

如果用邻接矩阵表示图,则查找每一个顶点的所有的边,所需时间为O(n),则时间复杂度为O(n^2).

2) 广度优先搜索BFS

算法思想:

访问了起始顶点v后,由v出发,依次访问v的各个未被访问过的邻接顶点w1, w2, w3,..., wt, 然后在顺序访问w1, w2, ... ,wt的所有还未被访问过的邻接顶点。再从这些访问过的邻接顶点出发,再访问它们的所有还未被访问过的邻接顶点,……如此做下去,直到图中所有顶点都被访问到为止。

进一步描述:

(1)从图中的某个顶点v出发,访问之;

(2)依次访问顶点v的各个未被访问过的邻接点,将v的全部邻接点都访问到;

(3)分别从这些邻接点出发,依次访问它们的未被访问过的邻接点,并使“先被访问过的顶点的邻接点” 先于“后被访问的顶点的邻接点”被访问,直到图中所有已被访问过的顶点的邻接点都被访问到。

//BFS
void Graph_Traverse(AdjGraph G)
{
	int* visited = new int[NumVertices];
	for(int i=0; i<G.n;i++)
		visited[i]=0;
	for(int i=0;i<G.n;i++)
		if(!visited[i])BFS(G,i,visited);

	delete[] visited;
}

void BFS(AdjGraph G, int v, int visited[])
{
	cout<<GetValue(G, v)<<" "<<endl;  //访问结点
	Queue<int>q;   //用队列来储存着一层正在访问的结点
	InitQueue(&q);
	EnQueue(&q,v); //进队列
	while(!QueueEmpty(&q))
	{
		Dequeue(&q,v);
		int w = GetFirstNeighbor(G,v);
		while(w!=-1)
		{
			if(!visited[w])
			{
				cout<<GetValue(G, w)<<" "<<endl;
			    visited[w]=1;
			    EnQueue(&q, w);
			}
			w=GetNextNeighbor(G,v,w);
		}
	}
	delete[] visited;
}

  

算法分析:

如果使用邻接表表示图,则循环的总时间代价为d0+d1+d2+ ... +d(n-1)=O(e),其中的di是顶点i的度。

如果使用邻接矩阵,则对于每一个被访问过的顶点,循环要检测矩阵中的n个元素,总的时间代价为O(n^2).

时间: 2024-12-24 09:03:42

Graph Algorithm的相关文章

[Algorithm] 如何正确撸&lt;算法导论&gt;CLRS

其实算法本身不难,第一遍可以只看伪代码和算法思路.如果想进一步理解的话,第三章那些标记法是非常重要的,就算要花费大量时间才能理解,也不要马马虎虎略过.因为以后的每一章,讲完算法就是这样的分析,精通的话,很快就读完了.你所说的证明和推导大概也都是在第三章介绍了,可以回过头再认真看几遍. 至于课后题,比较难,我只做了前几章,如果要做完需要更多时间和精力.这可以通过之后做算法题来弥补,可以去leetcode等网站找一些经典的算法题做一做,加深理解. Facebook的工程师写的攻略,介绍了用算法导论来

Algorithm lesson final exam

1.algorithm analysis O B/W/AV/AMOR,混入其他问题,设计+分析 2.传统算法(肯定要考) 1)divide and conquer master therem. recursive tree.分析复杂度.递归树加起来得到最终结果 2)greedy algorithm example sort->select 拟阵 独立系统的贪心模板,直接得到近似比 3)dynamic programming sub-optimal structrue.编辑距离 3.graph a

利用广度优先遍历(BFS)计算最短路径 - Java实现

我们用字符串代表图的顶点(vertax),来模拟学校中Classroom, Square, Toilet, Canteen, South Gate, North Gate几个地点,然后计算任意两点之间的最短路径. 如,我想从North Gate去Canteen, 程序的输出结果应为: BFS: From [North Gate] to [Canteen]: North Gate Square Canteen 首先定义一个算法接口Algorithm: public interface Algori

图算法系列-图的简单实现

最近看了很多介绍图算法的文章,发现网上可以搜到的资料比较少,所以打算在这写一个介绍图算法的系列文章,一方面是帮助自己整理,另一方面也给大家分享下这方面的知识. 1.1图的定义: 图(graph)由顶点(vertex)和边(edge)的集合组成,每一条边就是一个点对(v,w). 图的种类:地图,电路图,调度图,事物,网络,程序结构 图的属性:有V个顶点的图最多有V*(V-1)/2条边 1.2图的ADT: 1 struct Edge{ 2 int v,w; 3 Edge(int a=-1,int b

激光雷达点云数据处理相关算法库收集 【转】

1.CGAL,Computational Geometry Algorithms Library,计算几何算法库,设计目标是,以C++库的形式,提供方便,高效,可靠的几何算法.CGAL可用于各种需要几何计算的领域,如计算机图形学,科学可视化,计算机辅助设计和建模,地理信息系统,分子生物学,医学成像,机器人运动规划,网格生成,数值方法等等. 计算几何算法库(CGAL),提供计算几何相关的数据结构和算法,诸如三角剖分(2D约束三角剖分及二维和三维Delaunay三角剖分),Voronoi图(二维和三

Geeks - Union-Find Algorithm - Detect Cycle in a an Undirected Graph算法

利用Union Find的方法查找图中是否有环. 在于构建一个图数据结构,和一般图的数据结构不同的是这个图是记录了边的图,并在查找过程中不断把边连接起来,形成一个回路. 原文地址: http://www.geeksforgeeks.org/union-find/ #pragma once #include <stdio.h> #include <stdlib.h> #include <string.h> #include <algorithm> class

HDOJ 5409 CRB and Graph 无向图缩块

无向图缩块后,以n所在的块为根节点,dp找每块中的最大值. 对于每一个桥的答案为两块中的较小的最大值和较小的最大值加1 CRB and Graph Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 113    Accepted Submission(s): 41 Problem Description A connected, undi

codeforces 715B:Complete The Graph

Description ZS the Coder has drawn an undirected graph of n vertices numbered from 0 to n - 1 and m edges between them. Each edge of the graph is weighted, each weight is a positive integer. The next day, ZS the Coder realized that some of the weight

TCO14 2C L2: CliqueGraph,graph theory, clique

称号:http://community.topcoder.com/stat?c=problem_statement&pm=13251&rd=16017 參考:http://apps.topcoder.com/wiki/display/tc/TCO+2014+Round+2C 假设用先计算出每条边,用邻接矩阵来表示图,然后用BFS或 Floyd-Warshall算法来计算距离的话.时间复杂度是O(N^3),会超时.依据题名的提示知要利用clique graph的性质来做.基本思想是在BFS的