图的相关概念请查阅离散数学图这一章或者数据结构中对图的介绍。代码来自课本。
/*Graph存储结构*/
//邻接矩阵表示法
#define MAX_VERTEX_NUM 20 /*最多顶点个数*/
#define INFINITY 32768 /*表示极大值,即∞*/
/*图的种类:DG表示有向图,DN表示有向网,DUG表示无向图,UDN表示无向网*/
typedef enum {DG, DN, UDG, UDN} GraphKind; /*枚举类型*/
typedef char VertexData /*假设顶点数据为字符型*/
typedef struct ArcNode {
AdjType adj; /*对于无权图,用1或0表示是否相邻;对带权图,则为权值类型*/
OtherInfo info;
} ArcNode;
typedef struct {
VertexData vertex[MAX_VERTEX_NUM]; /*顶点向量*/
ArcNode arcs[MAX_VERTEX_NUM][MAX_VERTEX_NUM]; /*邻接矩阵*/
int vexnum,arcnum;
GraphKind kind;
} AdjMartrix; /*(AdjMartrix Matrix Graph)*/
/*采用邻接矩阵表示法创建有向图*/
int LocateVertex(AdjMartrix *G, VertexData v) { /*定位顶点位置函数*/
int j = ERROR, k;
for(k = 0; k < G->vexnum; k++) {
if(G->vertex[k] == v) {
j = k; break;
}
}
return j;
}
int CreateDN(AdjMartrix *G) {
int i,j,k,weight; VertexData v1,v2;
scanf("%d,%d", &G->arcnum; &G->vexnum); /*输入图的顶点数和弧数*/
for(i = 0; i < G->vexnum; i++) { /*初始化邻接矩阵*/
for(j = 0; j < G->vexnum; j++) {
G->arcs[i][j].adj = INFINITY;
}
}
for(i = 0; i < G->vertex; i++) { /*输入图的顶点*/
scanf("%c", &G->vertex)[i];
}
for(k = 0; k < G->arcnum; k++) { /*输入一条弧的两个顶点和权值*/
scanf("%c,%c,%d", &v1,&v2,&weight);
i = LocateVertex_M(G, v1);
j = LocateVertex_M(G, v2);
G->arcs[i][j].adj = weight; /*建立弧*/
}
return OK;
}
//邻接表表示法
#define MAX_VERTEX_NUM 20
typedef enum {DG, DN, UDG, UDN} GraphKind;
typedef struct ArcNode {
int adjvex; /*该弧指向顶点的位置*/
struct ArcNode *nextarc; /*指向下一条弧的指针*/
OtherInfo;
} ArcNode;
typedef struct VerNode {
VertexData data;
ArcNode *firstarc;
} VerNode;
typedef struct {
VertexNode vertex[MAX_VERTEX_NUM];
int vexnum,arcnum;
GraphKind kind;
} AdjList; /*Adjacency List Graph*/
//十字链表
#define MAX_VERTEX_NUM 20
typedef enum {DG, NG, UDG, UDN} GraphKind;
typedef struct ArcNode {
int tailvex,headvex;
struct ArcNode *hlink, *tlink;
} ArcNode;
typedef struct VertexNode {
VertexData data;
ArcNode *firstin, *firstout;
} VertexNode;
typedef struct {
VertexNode vertex[MAX_VERTEX_NUM];
int vexnum,arcnum; //图的顶点数和弧数
GraphKind kind;
} OrthList;
/*创建图的十字链表*/
void CrtOrthList(OrthList *g) {
/*从终端输入n个顶点的信息和e条弧的信息,以建立一个有向图的十字链表*/
scanf("%d,%d", &n,&e); /*从键盘输入图的顶点个数和弧的个数*/
g->vertex = n;
g->vertex = e;
for(i = 0; i < n; i++) { /*初始化顶点结点*/
scanf("%c", &(g->vertex[i].data));
g->vertex[i].firstin = NULL;
g->vertex[i].firstout = NULL;
}
for(k = 0; k < e; k++) { /*创建弧结点,建立弧结点个顶点的连接*/
scanf("%c,%c", &vt,&vh);
i = LocateVertex(g, vt);
j = LocateVertex(g, vh);
p = (ArcNode *)malloc(sizeof(ArcNode));
p->tailvex = i; p->headvex = j;
p->tlink = g->vertex[i].firstout;
g->vertex[i].firstout = p;
p->hlink = g->vertex[j];
g->vertex[j].firstin = p;
}
} /*CrtOrthList*/
/*邻接多重表*/
#define MAX_VERTEX_NUM 20
typedef struct EdgeNode {
int mark,ivex,jvex;
struct EdgeNode *ilink, *jlink;
} EdgeNode;
typedef struct {
VertexData data;
EdgeNode *firstedge;
} VertexNode;
typedef struct {
VertexNode vertexp[MAX_VERTEX_NUM];
int vernum,arcnum;
GraphKind kind;
} AdjMultiList;
/*图的深度遍历算法*/
#define True 1
#define False 0
#define Error -1
#define OK 1
int visited[MAX_VERTEX_NUM]; /*初始化标准数组*/
void TraverseGraph(Graph g) {
/*在图g中寻找未访问的顶点作为起始点,并调用深度优先搜索过程进行遍历。Graph表示图的
一种存储结构,如邻接矩阵或者邻接表等*/
for(vi = 0; vi < g.vexnum; vi++) Visited[vi] = False; /*访问标志数组*/
for(vi = 0; vi < g.vexnum; vi++) { //循环调用深度优先遍历连通子图,若g是连通图,则此
if(!visted[vi]) DepthFirstSearch(g,vi); //仅调用一次
}
} /*TraverseGraph*/
/*深度优先遍历v0所在的连通子图*/
void DepthFirstSearch(Graph g, int v0) {
visit(v0); visit[v0] = True; /*访问顶点v0,修改访问变量*/
w = FirstAdjVertex(g, v0);
while(w != -1) {
if(!visited[w]) DepthFirstSearch(g, w); /*递归调用DepthFirstSearch*/
w = NextAdjVertex(g, v0, w); /*找下一个邻接点*/
}
} /*DepthFirstSearch*/
/*采用邻接矩阵的DepthFirstSearch*/
void DepthFirstSearch(AdjMartrix g, int v0) {
visit(v0); visited[vo] = True;
for(vj = 0; vj < g.vexnum; vj++) {
if(!visited[vj] && g.arcs[v0][vj].adj == 1) { //未访问过且路径存在
DepthFirstSearch(g, vj);
}
}
} /*DepthFirstSearch*/
/*采用邻接表的DepthFiirstSearch*/
void DepthFirstSearch(AdjList g, int v0) {
visit(v0); visited[v0] = True;
p = g.vertex[v0].firstarc;
while(p != NULL) {
if(!visited[p->adjvex]) DepthFirstSearch(g, p->adjvex);
p = p->nextarc;
}
} /*DepthFirstSearch*/
/*非递归形式的DepthFirstSearch*/
void DepthFirstSearch(Graph g, int v0) {
/*从v0出发深度优化搜索图g*/
InitStack(&s);
Push(&S, v0);
while(!is Empty(S)) {
Pop(&S, &v);
if(!visited[v]) {
visit(v);
visited[v] = True;
w = FirstAdjVertex(g, v);
while(w != -1) {
if(!visted[w]) {
Push(&S, w);
}
w = NextAdjVertex(g, v, w); /*求v相对于w的下一个邻接点*/
}
}
}
}
/*广度优先搜索图g中v0所在的连通子图*/
void BreadthFirstSearch(Graph g, int v0) {
visit(v0); visited[v0] = True;
InitQueue(&Q);
EnterQueue(&Q, v0);
while(Empty(&Q, v0)) {
DeleteQueue(&Q, &v);
w = FirstAdjVertex(g, v);
while(w != -1) {
if(!visited[w]) {
visit(w); visited[w] = True;
EnterQueue(&Q, w);
}
w = NextAdjVertex(g, v, w);
}
}
}
/*图的应用*/
/*深度优先找出从顶点u到v的简单路径*/
int *pre;
void one_path(Graph *G, int u, int v) {
int i;
pre = (int *)malloc(G->vexnum * sizeof(int));
for(i = 0; i < G->vexnum; i++) { /*初始化,置-1*/
pre[i] = -1;
}
pre[u] = -2; /*将pre[u]置-2,表示已访问过,且没有前驱*/
DFS_path(G, u, v); /*用深度优先算法找出一条从u到v的简单路径*/
free(pre);
}
int DFS_path(Graph *G, int u, int v) {
int j;
for(j = firstadj(G, u)); j >= 0; j = nextadj(G, u, j)) {
if(pre[j] == -1) { //不等于-1则参数有误
pre[j] = u;
if(j == v) {
print_path(pre, v); //从v0开始,沿着pre[]中保留的前驱指针输出路径(直到-2)
}
else if(DFS_path(G, j, v)); return 1;
}
}
return 0;
}
/*求图的最小生成树*/
/*prim算法(加点法)*/
struct {
int adjvex;
int lowcost;
} closedge[MAX_VERTEX_NUM]; /*求最小生成树时的辅助数组*/
MiniSpanTree_Prim(AdjMartrix gn, int u) {
/*从顶点u出发,按prim算法构造连通网gn的最小生成树,并输出生成时的每条边*/
closedge[u].lowcost = 0; /*初始化*, U = {u}*/
for(i = 0; i < gn.vexnum; i++) {
if(i != u) { /*对V-U的顶点i,初始化closedge[i]*/
closedge[i].adjvex = u;
closedge[i].lowcost = gn.arcs[u][i].adj;
}
}
for(e = 1; e < gn.vexnum - 1; e++) { /*找n-1条边*/
v = Mimium(closedge); /*closedge中存有当前最小边(u,v)的信息*/
printf(u, v); /*输出生成树的当前最小边(u,v)*/
closedge[v].lowcost = 0; /*将顶点v纳入U集合*/
for(i = 0; i < gn.vexnum; i++) { /*顶点v纳入U集合后,更新closedge[i]*/
if(gn.arcs[v][i].adj < closedge[i].lowcost) {
closedge[i].lowcost = gn.arcs[v][i].adj;
closedge[i].adj = v;
}
}
}
}