图论基础
来源:互联网 发布:启动子数据库 编辑:程序博客网 时间:2024/04/29 19:03
图的表示
常用的两种方法:
邻接表与邻接矩阵
每一个点对应一个集合set(邻接表),存储与此点相连的点。
1.
-)点用连续存储
a. 邻接表用连续存储表
b. 邻接表用链式表
List neighbors[max_size];
二)点与邻接表都用链式表
class Edge{
Vertex *end_point; //边的终点
Edge *next_edge; //邻接表的下一条边
}
class Vertex{
Edge *first_edge; // 邻接表的第一条边
Vertex *next_vertex; // 下一个点
class digraph
{
Vertex *first_vertex;
}
2. 固定集合大小max_set, 看成是bit string, 可以用STL中的bitset. 其实质上是下面的邻接矩阵.
邻接矩阵:
或者干脆用二维数组。
bool adjcency[max_size][max_size];
当表示无向图时有adjcency[v][w]=adjcency[w][v];
表示有向图时, adjcency[v][w]表示图中是否有从v到w的边.
权
以上方式都可以表示边的权,
例如用链式表时,可在Edge加个变量weight。
List的Record包含权值与点的标号。
而邻接矩阵就用Record代替bool。
图的遍历
DFS(深度优先搜索)
递归算法
visit(V);
for(each vertex w adjacent to v)
traverse(w);
1,图可能有回路的,为防止死循环,需要设置是否已经访问标记。
2,图可能不连通,需要对每一个点都进行DFS。
template <int max_size> // 注意template奇怪用法
void Digraph<max_size>::depth_first(void (*visit)(Vertex &)) const
{
bool visited[max_size];
Vertex v;
for (all v in G) visited[v] = false;
for (all v in G) if (!visited[v])
traverse(v, visited, visit);
}
template <int max_size>
void Digraph<max_size>::traverse(Vertex &v, bool visited[],
void (*visit)(Vertex &)) const
/*
Pre: v is a vertex of the Digraph.
Post: The depth-first traversal, using function *visit, has been completed
for v and for all vertices that can be reached from v.
Uses: traverse recursively.
*/
{
Vertex w;
visited[v] = true;
(*visit)(v);
for (all w adjacent to v)
if (!visited[w])
traverse(w, visited, visit);
}
BFS(广度优先搜索)
队列+标记
拓扑排序(有向无回路图acyclic)
每个点出现在它的后继之前。
DFS:
递归: 找到没有后继的节点放到后面。
O(V+E)
BFS:
维护一个数组,记录每个点的前继的数目。先双重循环初始化其前继数目,
将前继数目为0的插入到拓扑队列中去
BFS: 当结点前继数目为0时, 说明此结点可以插入到拓扑序列中去, 然后一个循环相应的前继数目减一。
单源最短路径(权非负)
Dijkstra
贪心: 每次将到当前点集合中未访问的距离最短的节点加入到当前点集合中
常用的两种方法:
邻接表与邻接矩阵
每一个点对应一个集合set(邻接表),存储与此点相连的点。
1.
-)点用连续存储
a. 邻接表用连续存储表
b. 邻接表用链式表
List neighbors[max_size];
二)点与邻接表都用链式表
class Edge{
Vertex *end_point; //边的终点
Edge *next_edge; //邻接表的下一条边
}
class Vertex{
Edge *first_edge; // 邻接表的第一条边
Vertex *next_vertex; // 下一个点
class digraph
{
Vertex *first_vertex;
}
2. 固定集合大小max_set, 看成是bit string, 可以用STL中的bitset. 其实质上是下面的邻接矩阵.
邻接矩阵:
或者干脆用二维数组。
bool adjcency[max_size][max_size];
当表示无向图时有adjcency[v][w]=adjcency[w][v];
表示有向图时, adjcency[v][w]表示图中是否有从v到w的边.
权
以上方式都可以表示边的权,
例如用链式表时,可在Edge加个变量weight。
List的Record包含权值与点的标号。
而邻接矩阵就用Record代替bool。
图的遍历
DFS(深度优先搜索)
递归算法
visit(V);
for(each vertex w adjacent to v)
traverse(w);
1,图可能有回路的,为防止死循环,需要设置是否已经访问标记。
2,图可能不连通,需要对每一个点都进行DFS。
template <int max_size> // 注意template奇怪用法
void Digraph<max_size>::depth_first(void (*visit)(Vertex &)) const
{
bool visited[max_size];
Vertex v;
for (all v in G) visited[v] = false;
for (all v in G) if (!visited[v])
traverse(v, visited, visit);
}
template <int max_size>
void Digraph<max_size>::traverse(Vertex &v, bool visited[],
void (*visit)(Vertex &)) const
/*
Pre: v is a vertex of the Digraph.
Post: The depth-first traversal, using function *visit, has been completed
for v and for all vertices that can be reached from v.
Uses: traverse recursively.
*/
{
Vertex w;
visited[v] = true;
(*visit)(v);
for (all w adjacent to v)
if (!visited[w])
traverse(w, visited, visit);
}
BFS(广度优先搜索)
队列+标记
拓扑排序(有向无回路图acyclic)
每个点出现在它的后继之前。
DFS:
递归: 找到没有后继的节点放到后面。
O(V+E)
BFS:
维护一个数组,记录每个点的前继的数目。先双重循环初始化其前继数目,
将前继数目为0的插入到拓扑队列中去
BFS: 当结点前继数目为0时, 说明此结点可以插入到拓扑序列中去, 然后一个循环相应的前继数目减一。
单源最短路径(权非负)
Dijkstra
贪心: 每次将到当前点集合中未访问的距离最短的节点加入到当前点集合中
- 图论基础
- 图论基础
- 图论基础
- 图论基础
- 图论基础
- 图论基础
- 图论基础
- 图论基础
- 数据结构:图论基础
- 图论基础UVA10054
- 图论基础UVA11624
- 图论基础UVA10047
- 图论算法基础
- 图论基础算法
- 图论基础
- 图论基础
- 图论基础
- 图论基础
- 嵌入式开发中使用DDD进行调试
- 母亲颂
- Java文件操作详解
- Oracle数据库应用中几种基本数据引用关系中的特殊查询
- ASCII 编码表
- 图论基础
- 趋势曝行业内幕:有杀毒厂商故意误杀?
- C++ string转换为char*
- java c/s通信
- Python语言介绍
- 使用tomcat,不再deploy
- Java Annotation之自定义篇 (2)
- 黑客的思想
- 硅谷涌动搜索创业潮 赶超Google是共同目标(推荐帖)