1.图的表示
1)邻接矩阵
对于普通图,0 /1
对于网络(或带权图),邻接矩阵的值 0/N
2)邻接表
如果点多边少,用邻接矩阵很浪费存储空间,这时候用邻接表。
用邻接表的话,如果想得到顶点的入度,必须检测其他所有顶点对应的边链表,这时候可以建立逆邻接表。
3.邻接多重表
邻接多重表在要求每条边处理一次的实际应用中特别有用。
2.图的遍历
1)深度优先遍历(DFS)
给每个点一个位记录是否已经访问;要使用递归。
算法代码:
//从顶点位置v出发
void DFS(Graph G,int v,bool visited[]){
visited[v]=true;
int w=G.getFirstNeighbor(v);
while(w!=-1){
if(visited[w]==false)
DFS(G,w,visited);
w=G.getNextNeighbor(v,w);
}
};
2)广度优先遍历(BFS)
给每个点一个位记录是否已经访问;要用到一个队列;不递归。
void BFS(Graph G){
Queue q;
Q.enqueue(v);
while(!q.empty()){
int v=q.dequeue();
int d=G.getFirstNeighbor(v);
while(d!=-1){
if(visited(d)==false)
visited(d)=true;
q.enqueue(d);
d=G.getNextNeighbor(v);
}
}
}
3.最小生成树
1)Kruskal算法
每次选出一条具有最小权值,且两端点不在同一连通分量上的边,加入生成树。
2)Prim算法
每次选出一个端点在生成树中,另一个端点不在生成树中的权值最小的边加入生成树中。
4.最短路径
1)非负权值的单元最短路径_Dijkstra算法
(以下转自http://www.cnblogs.com/biyeymyhjob/archive/2012/07/31/2615833.html)
[cpp] view plaincopy
const int MAXINT = 32767;
const int MAXNUM = 10;
int dist[MAXNUM];
int prev[MAXNUM];
int A[MAXNUM][MAXNUM];
void Dijkstra(int v0)
{
bool S[MAXNUM]; // 判断是否已存入该点到S集合中
int n=MAXNUM;
for(int i=1; i<=n; ++i)
{
dist[i] = A[v0][i];
S[i] = false; // 初始都未用过该点
if(dist[i] == MAXINT)
prev[i] = -1;
else
prev[i] = v0;
}
dist[v0] = 0;
S[v0] = true;
for(int i=2; i<=n; i++)
{
int mindist = MAXINT;
int u = v0; // 找出当前未使用的点j的dist[j]最小值
for(int j=1; j<=n; ++j)
if((!S[j]) && dist[j]<mindist)
{
u = j; // u保存当前邻接点中距离最小的点的号码
mindist = dist[j];
}
S[u] = true;
for(int j=1; j<=n; j++)
if((!S[j]) && A[u][j]<MAXINT)
{
if(dist[u] + A[u][j] < dist[j]) //在通过新加入的u点路径找到离v0点更短的路径
{
dist[j] = dist[u] + A[u][j]; //更新dist
prev[j] = u; //记录前驱顶点
}
}
}
}
算法实例
先给出一个无向图
用Dijkstra算法找出以A为起点的单源最短路径步骤如下
2)任意权值的单源最短路径_Bellman-Ford算法
主要是两点:
1.此路径最多有n-1条边
2.递推式
3)所有顶点之间的最短路径_Floyd算法
[cpp] view plaincopy
typedef struct
{
char vertex[VertexNum]; //顶点表
int edges[VertexNum][VertexNum]; //邻接矩阵,可看做边表
int n,e; //图中当前的顶点数和边数
}MGraph;
void Floyd(MGraph g)
{
int A[MAXV][MAXV];
int path[MAXV][MAXV];
int i,j,k,n=g.n;
for(i=0;i<n;i++)
for(j=0;j<n;j++)
{
A[i][j]=g.edges[i][j];
path[i][j]=-1;
}
for(k=0;k<n;k++)
{
for(i=0;i<n;i++)
for(j=0;j<n;j++)
if(A[i][j]>(A[i][k]+A[k][j]))
{
A[i][j]=A[i][k]+A[k][j];
path[i][j]=k;
}
}
}
5.AOV网络(activity on vertice)
拓扑排序:
每次选出入度为0的顶点,然后去掉这个顶点以及它的发出边。