图的基本算法
2013-08-31 20:18
453 查看
1 图的表示
图的表示无外乎两种,邻接表表示法和邻接矩阵表示法。
对于上图,用邻接表表示如下:
1->2>5
2->1->3->4->5
3->2->4
4->2->5->3
5->1->2->4
而用邻接矩阵表示如下
1 2 3 4 5
1 0 1 0 0 1
2 1 0 1 1 1
3 0 1 0 1 0
4 0 1 1 0 1
5 1 1 0 1 0
上面两种表示只是无向图的表示而已,图还分为有向图和无向图,表示方法都一样,无向图就好像是有向图中相连的顶点互相可达且路径长度为1.
在邻接矩阵中,矩阵内各元素定义为如果两个顶点i和j存在边,那么矩阵A中的元素aij=1,否则为0.
2.广度优先搜索
在给定图G=(V,E)和一个源点s的情况下,广度优先搜索系统的探索G中的边,以期发现可从s到达的所有顶点,并计算这些可达顶点之间的距离。该搜索算法可以生成一棵以源点s为根,且包含s的可达顶点的广度优先树。
为了记录搜索的轨迹,广度优先搜索将每个顶点着色为白色,灰色和黑色。在搜索开始时,所有顶点都是白色的,随着搜索的进行各顶点逐渐变为灰色,然后变为黑色。搜索中第一次碰到某一个顶点时,称该顶点被发现了,此时该顶点变为非白色。因此,灰色和黑色顶点都是已经被发现的,但广度优先搜索还是对他们进行了区分,以确保搜索时以一种广度优先的方式进行的。
广度优先搜索构造了一棵广度优先树,它在开始时只包含一个根顶点,即源顶点s。在某个已发现的顶点u的邻接表的过程中,每当发现一个白色顶点v,该顶点v即便(u,v)就被添加到树中。
下面的广度优先搜索过程BFS假定输入图G=(V,E)采用邻接表表示,对于图中的每个顶点,还采用了几种另外的数据结构,对每个顶点u属于V,其色彩存储在变量color[u]中,u的父母存在变量p[u]中。如果u没有父母,那么p[u]=NIL,由该算法算出的源顶点s和顶点u的距离存在变量d[u]中,该算法还采用了先进先出队列Q。
下面是BFS过程
BFS
For each vertex u belong V[G]-{s};
Do color[u]=WHITE;
D[u]=inf
P[u]=NIL
Color[s]=GRAY
D[s]=0
P[s]=NIL
Q=NULL
While Q!=NULL
Do u=DEQUEUE(Q)
For each vadj(u)
Do ifcolor[u]==WHITE
Thencolor[v]=GRAY
D[v]=d[u]+1
P[v]=u
Enqueue(Q,v)
Color[u]=BLACK;
下面是打印源点s到某一顶点v的路径
PRINT_PATH(G,s,v)
If v==s
Then print s
Else if p[v]=NIL
Then print “nopath from s to v”
ElsePRINT_PATH(G,s,p[v])
Print v
下面是我的源代码:
#include <list>
#include <queue>
#include <iostream>
#include <fstream>
using namespace std;
int dis[5];
int color[5];
int p[5];
void dfs(list<int> *arr,int s)
{
queue<int>q;
q.push(s);
p[s]=0;
dis[s]=0;
color[s]=2;
int u;
list<int>::iteratorpos;
while(!q.empty())
{
u=q.front();
q.pop();
pos=arr[u].begin();
while(pos!=arr[u].end())
{
if(color[*pos-1]==1)
{
if(dis[*pos-1]>dis[u]+1)
{
p[*pos-1]=u;
dis[*pos-1]=dis[u]+1;
color[*pos-1]=2;
}
q.push(*pos-1);
}
++pos;
}
color[u]=0;
}
for(inti=0;i<5;i++)
{
cout<<dis[i]<<'';
}
cout<<endl;
}
int main()
{
ifstreamcin("a.txt");
int n,i,j,from,to;
cin>>n;
list<int>*arr=new list<int>
;
list<int>::iteratorpos;
for(i=0;i<n;i++)
{
dis[i]=10000;
color[i]=1;
p[i]=-1;
}
while(cin>>from>>to&& from!=to)
{
arr[from-1].push_back(to);
}
cout<<"--------------"<<endl;
for(i=0;i<n;i++)
{
pos=arr[i].begin();
while(pos!=arr[i].end())
{
cout<<*pos<<'';
++pos;
}
cout<<endl;
}
cout<<"--------------"<<endl;
dfs(arr,0);
return 0;
}
这个算法只能用于上面的无向图,对于其图相应的改一下数组的长度以及循环中的次数即可
3.深度优先搜索
正如深度优先搜索这一名称一样,这种搜索算法是尽可能“深”的搜索一个图。
废话不多说,直接上伪代码
DFS(G)
For each vertex u belong V[G]
Do color[u]=WHITE
P[u]=NIL
Time=0
For each vertex u belong V[G]
Do ifcolor[u]=WHITE
ThenDFS_VISIT(u)
DFS_VISIT(u)
Color[u]=GRAY
Time=time+1;
D[u]=time
For each v adj(u)
Do ifcolor[v]==WHITE
P[v]=u
DFS_VISIT(v)
Color[u]=BLACK
F[u]=time=time+1
上面的深度优先搜索伪代码中,在搜索的同时为每个顶点加上时间戳,每个顶v有两个时间戳,当顶点v第一次被发现时,记录下第一个时间戳d[v],当结束检查v的邻接表时,记录下第二个时间戳f[v].
源代码:
#define BLACK 0
#define WHITE 1
#define GRAY 2
int n=10;
int color[10],d[10],f[10],p[10];
int time;
void Dfs(list<int>*arr,int u)
{
color[u]=GRAY;
time=time+1;
d[u]=time;
list<int>::iteratorpos=arr[u].begin();
for(;pos!=arr[u].end();++pos)
{
if(WHITE==color[*pos-1])
{
p[*pos-1]=u;
Dfs(arr,*pos-1);
}
}
color[u]=BLACK;
f[u]=time=time+1;
}
void dfs(list<int> *arr)
{
int i;
time=0;
for(i=0;i<n;i++)
{
color[i]=WHITE;
p
=-1;
}
for(i=0;i<n;i++)
{
if(color[i]==WHITE)
Dfs(arr,i);
}
}
4000
图的表示无外乎两种,邻接表表示法和邻接矩阵表示法。
对于上图,用邻接表表示如下:
1->2>5
2->1->3->4->5
3->2->4
4->2->5->3
5->1->2->4
而用邻接矩阵表示如下
1 2 3 4 5
1 0 1 0 0 1
2 1 0 1 1 1
3 0 1 0 1 0
4 0 1 1 0 1
5 1 1 0 1 0
上面两种表示只是无向图的表示而已,图还分为有向图和无向图,表示方法都一样,无向图就好像是有向图中相连的顶点互相可达且路径长度为1.
在邻接矩阵中,矩阵内各元素定义为如果两个顶点i和j存在边,那么矩阵A中的元素aij=1,否则为0.
2.广度优先搜索
在给定图G=(V,E)和一个源点s的情况下,广度优先搜索系统的探索G中的边,以期发现可从s到达的所有顶点,并计算这些可达顶点之间的距离。该搜索算法可以生成一棵以源点s为根,且包含s的可达顶点的广度优先树。
为了记录搜索的轨迹,广度优先搜索将每个顶点着色为白色,灰色和黑色。在搜索开始时,所有顶点都是白色的,随着搜索的进行各顶点逐渐变为灰色,然后变为黑色。搜索中第一次碰到某一个顶点时,称该顶点被发现了,此时该顶点变为非白色。因此,灰色和黑色顶点都是已经被发现的,但广度优先搜索还是对他们进行了区分,以确保搜索时以一种广度优先的方式进行的。
广度优先搜索构造了一棵广度优先树,它在开始时只包含一个根顶点,即源顶点s。在某个已发现的顶点u的邻接表的过程中,每当发现一个白色顶点v,该顶点v即便(u,v)就被添加到树中。
下面的广度优先搜索过程BFS假定输入图G=(V,E)采用邻接表表示,对于图中的每个顶点,还采用了几种另外的数据结构,对每个顶点u属于V,其色彩存储在变量color[u]中,u的父母存在变量p[u]中。如果u没有父母,那么p[u]=NIL,由该算法算出的源顶点s和顶点u的距离存在变量d[u]中,该算法还采用了先进先出队列Q。
下面是BFS过程
BFS
For each vertex u belong V[G]-{s};
Do color[u]=WHITE;
D[u]=inf
P[u]=NIL
Color[s]=GRAY
D[s]=0
P[s]=NIL
Q=NULL
While Q!=NULL
Do u=DEQUEUE(Q)
For each vadj(u)
Do ifcolor[u]==WHITE
Thencolor[v]=GRAY
D[v]=d[u]+1
P[v]=u
Enqueue(Q,v)
Color[u]=BLACK;
下面是打印源点s到某一顶点v的路径
PRINT_PATH(G,s,v)
If v==s
Then print s
Else if p[v]=NIL
Then print “nopath from s to v”
ElsePRINT_PATH(G,s,p[v])
Print v
下面是我的源代码:
#include <list>
#include <queue>
#include <iostream>
#include <fstream>
using namespace std;
int dis[5];
int color[5];
int p[5];
void dfs(list<int> *arr,int s)
{
queue<int>q;
q.push(s);
p[s]=0;
dis[s]=0;
color[s]=2;
int u;
list<int>::iteratorpos;
while(!q.empty())
{
u=q.front();
q.pop();
pos=arr[u].begin();
while(pos!=arr[u].end())
{
if(color[*pos-1]==1)
{
if(dis[*pos-1]>dis[u]+1)
{
p[*pos-1]=u;
dis[*pos-1]=dis[u]+1;
color[*pos-1]=2;
}
q.push(*pos-1);
}
++pos;
}
color[u]=0;
}
for(inti=0;i<5;i++)
{
cout<<dis[i]<<'';
}
cout<<endl;
}
int main()
{
ifstreamcin("a.txt");
int n,i,j,from,to;
cin>>n;
list<int>*arr=new list<int>
;
list<int>::iteratorpos;
for(i=0;i<n;i++)
{
dis[i]=10000;
color[i]=1;
p[i]=-1;
}
while(cin>>from>>to&& from!=to)
{
arr[from-1].push_back(to);
}
cout<<"--------------"<<endl;
for(i=0;i<n;i++)
{
pos=arr[i].begin();
while(pos!=arr[i].end())
{
cout<<*pos<<'';
++pos;
}
cout<<endl;
}
cout<<"--------------"<<endl;
dfs(arr,0);
return 0;
}
这个算法只能用于上面的无向图,对于其图相应的改一下数组的长度以及循环中的次数即可
3.深度优先搜索
正如深度优先搜索这一名称一样,这种搜索算法是尽可能“深”的搜索一个图。
废话不多说,直接上伪代码
DFS(G)
For each vertex u belong V[G]
Do color[u]=WHITE
P[u]=NIL
Time=0
For each vertex u belong V[G]
Do ifcolor[u]=WHITE
ThenDFS_VISIT(u)
DFS_VISIT(u)
Color[u]=GRAY
Time=time+1;
D[u]=time
For each v adj(u)
Do ifcolor[v]==WHITE
P[v]=u
DFS_VISIT(v)
Color[u]=BLACK
F[u]=time=time+1
上面的深度优先搜索伪代码中,在搜索的同时为每个顶点加上时间戳,每个顶v有两个时间戳,当顶点v第一次被发现时,记录下第一个时间戳d[v],当结束检查v的邻接表时,记录下第二个时间戳f[v].
源代码:
#define BLACK 0
#define WHITE 1
#define GRAY 2
int n=10;
int color[10],d[10],f[10],p[10];
int time;
void Dfs(list<int>*arr,int u)
{
color[u]=GRAY;
time=time+1;
d[u]=time;
list<int>::iteratorpos=arr[u].begin();
for(;pos!=arr[u].end();++pos)
{
if(WHITE==color[*pos-1])
{
p[*pos-1]=u;
Dfs(arr,*pos-1);
}
}
color[u]=BLACK;
f[u]=time=time+1;
}
void dfs(list<int> *arr)
{
int i;
time=0;
for(i=0;i<n;i++)
{
color[i]=WHITE;
p
=-1;
}
for(i=0;i<n;i++)
{
if(color[i]==WHITE)
Dfs(arr,i);
}
}
4000
相关文章推荐
- java 数据结构基本算法希尔排序
- 算法总结笔记之一——线性表(1)基本实现【C++语言】
- 【基本算法】求解最大公约数
- 中文分词基本算法主要分类
- 【openjudge 9275】[2.6基本算法之动态规划][Usaco2009 Feb]Bullcow(dp)
- JAVA中关于链表的操作和基本算法
- 基本算法思想
- uva 101 The Blocks Problem (基本算法-模拟)
- C++单链表的基本算法
- 基本图形生成算法
- java基本算法总结(冒泡排序、选择排序、插入排序)
- 第十二周 项目一--图基本算法库
- 瞬间模糊检索1000万基本句型的语言算法
- LCA 最近公共祖先 Tarjan(离线)算法的基本思路及其算法实现
- Latex:基本用法、表格、公式、算法(持续更新)
- 普林斯顿公开课 算法4-1:优先级队列API和基本实现
- c语言基本算法程序百例之九—杨辉三角形
- 计算机专业大一需要掌握的基本算法
- 瞬间模糊搜索1000万基本句型的语言算法
- scikit-learn的基本用法(一)——KNN算法的使用