图知识点思维导图
图代码实现
1. 图的存储
1.1 邻接矩阵法
#define MaxVertexNum 100
typedef char VertexType;
typedef int EdgeType;
typedef struct{
VertexType Vex[MaxVertexNum];
EdgeType Edge[MaxVertexNum][MaxVertexNum];
int vexnum,arcnum;
}MGraph;
1.2 邻接表法
#define MaxVertexNum 100
typedef struct ArcNode{
int adjvex;
struct ArcNode *next;
}ArcNode;
typedef struct VNode{
VertexType data;
ArcNode *first;
}VNode,AdjList[MaxVertexNum];
typedef struct{
AdjList vertices;
int vexnum,arcnum;
}ALGraph;
1.3 十字链表法
十字链表是有向图的一种链式存储结构
#define MaxVertexNum 100
typedef struct ArcNode{
int tailcex,headvex;
struct ArcNode *hlink,*tlink;
}ArcNode;
typedef struct VNode{
VertexType data;
ArcNode *fristin, *firstout;
}VNode;
typedef struct {
VNode xlist[MaxVerNum];
int vexnum,arcnum;
}GLGraph;
1.4 邻接多重表法
邻接多重表是无向图的另一种链式存储方式
#define MaxVertexNum 100
typedef struct ArcNode{
bool mark;
int ivex,jvex;
struct ArcNode *llink,*jlink;
}ArcNode;
typedef struct VNode{
VertexType data;
ArcNode *fristedge;
}VNode;
typedef struct {
VNode adjmulist[MaxVerNum];
int vexnum,arcnum;
}AMLGraph;
2. 图的遍历
2.1 广度优先遍历BFS
图的广度优先遍历类似于二叉树的层次遍历,借助队列来实现
bool visit[MAX_VERTEX_NUM];
void BSFTraverse(Graph G){
for(i = 0 ; i<G.vexnum ;++i)
visit[i]=false;
InitQueue(Q);
for(int i = 0;i<G.vexnum;++i)
if(!visited[i])
BFS(G,i);
}
void BFS(Graph G,int v){
visit(v);
visited[v] = TRUE;
Enqueue(Q,v);
while(!isEmpty(Q)){
DeQueue(Q,v);
for(w=FirstNeighbor(G,v);w>=0;w=NextNeighbor(G,v,w)){
if(!visited[w]){
visit(w);
visited[w]=TRUE;
EnQueue(Q,w);
}
}
}
}
2.1.1 BFS算法求解单源最短路径问题
void BFS_MIN_Distance(Graph G,int u){
for(int i = 0; i<G.vexnum;++i)
d[i]=INFINITY;
visited[u]=true;
d[u]=0;
EnQueue(Q,u);
while(!IsEmpty(Q)){
DeQueue(Q,u);
for(w=FirstNeighbor(G,v);w>=0;w=NextNeighbor(G,u,w)){
if(!visited[w]){
visited[w]=true;
d[w]=d[u]+1;
EnQueue(Q,w);
}
}
}
2.2 深度优先搜索DFS
图的深度优先遍历类似于树的先序遍历,借助递归栈来实现
bool visit[MAX_VERTEX_NUM];
void DSFTraverse(Graph G){
for(v = 0 ; v<G.vexnum ;++v)
visit[v]=false;
for(v = 0;v<G.vexnum;++v)
if(!visited[v])
DFS(G,v);
}
void DFS(Graph G,int v){
visit(v);
visited[v] = true;
for(w=FirstNeighbor(G,v);w>=0;w=NextNeighbor(G,v,w)){
if(!visited[w]){
DFS(G,w);
}
}
}
3. 图的应用
3.1 最小生成树
GENERIC_MST(G){
T=NULL;
while T 未形成一颗生成树;
do 找到一条最小代价边(u,v)并且加入T后不会产生回路;
T = T(u,v);
}
3.1.1 Prime算法
思想(选顶点):先选一个顶点加入T中,选择一个与T中顶点集合距离最近的顶点,并将此顶点和相应的边加入T中,每次操作后顶点数和边数加一。以此类推,知道所有顶点都加入T中。
void Prim(G,T){
T=;
U={w};
while((v-U)!= ){
设(u,v)是使u U与v (V-U),且权值最小的边;
T=T{(u,v)};
U=U {v};
}
}
3.1.1 Kruskal算法
思想(选边):初始时为只有n个顶点而无边的非连通图,每个顶点自成一个连通分量,按照权值由小到大排序,不断选取当前未被选取过且权值最小的边,若该边依附的顶点落在T中不同的连通分量上,则将此边加入T,否则舍弃此边而选择下一条权值最小的边。以此类推,直至T中所有顶点都在一个连通分量上。
void Kruskal(V ,T){
T=v;
numS=n;
while(numS>1){
从E中取出权值最小的边(v ,u);
if(v和u属于T中不同的连通分量){
T=T {(v ,u)};
numS--;
}
}
3.2 拓扑排序
3.2.1 拓扑排序
bool TopologicalSort(Graph G){
InitStack(S);
for(int i = 0; i < G.vexnum; ++i){
if(indegree[i]==0)
Push(S,i);
}
int count = 0;
while(!IsEmpty(S)){
Pop(S,i);
print[count++]=i;
for(p=G.vertices[i].firstarc;p=p->nextarc){
v = p->adjvex;
if(!(--indegree[v]))
Push(S,v);
}
}
if(count < G.vexnum)
return false;
else
return true;
}
3.2.2 逆拓扑排序(DFS算法)
void DFSTraverse(Graph G){
for(v = 0; v<G.vexnum;++v)
vivited[v] = flase;
for(v = 0; v<G.vexnum;++v)
if(!visited[v])
DFS(G,v);
}
void DFS(Graph G,int v){
visit(v);
visited[v] = true;
for(w=FirstNeighbor(G,v);w>=0;w=NextNeighor(G,v,W))
if(!visited[w]){
DFS(g,W);
}
print(v);
}
邻接矩阵存储结构的 NextNeighbor 函数:
int NextNeighbor(MGraph &G, int x, int y){
if(x != -1&&y != -1){
for (int col=y+1;col < G.vexnum ; col++){
if(G.Edge[x][col]>0 && G.Edge[x][co1]<maxWeight)
return col;
}
}
return -1;
}
邻接表做存储结构的 NextNeighbor 函数:
int NextNeighbor(ALGraph &G, int x, int y){
if(x != -1){
ArcNode *p=G.vertices[x].first;
while(p!=NULL&&p->data!=y)
p = p->next;
if(p!=NULL&&p->next !=NULL)
return p->next->data;
}
return -1;
}
|