第6章 图代码
使用建议
- 先配合对应章节阅读:第6章 图 正文
- 这一页优先提供站内可直接查看的代码版本,适合网页阅读和搜索。
- 这一页主要用于网页阅读,建议结合对应正文与逐行注释版一起使用。
文件位置
- 普通代码版:
第6章普通代码版
- 逐行注释版:
第6章逐行注释版代码
- 兼容编码版:
第6章兼容编码版逐行注释代码
普通代码版
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_VERTEX_NUM 20
#define INF 1000000000
/* 邻接矩阵图结构:vexs 保存顶点名,edges 保存边权,vexnum/arcnum 记录规模。 */
typedef struct {
char vexs[MAX_VERTEX_NUM];
int edges[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
int vexnum;
int arcnum;
bool directed;
} AMGraph;
/* 邻接表边结点:adjvex 是邻接点下标,weight 是边权,nextarc 指向下一条边。 */
typedef struct ArcNode {
int adjvex;
int weight;
struct ArcNode *nextarc;
} ArcNode;
/* 邻接表顶点结点:data 保存顶点名,firstarc 指向第一条出边。 */
typedef struct {
char data;
ArcNode *firstarc;
} VNode;
/* 邻接表图结构:vertices 保存所有顶点,vexnum/arcnum 记录规模。 */
typedef struct {
VNode vertices[MAX_VERTEX_NUM];
int vexnum;
int arcnum;
bool directed;
} ALGraph;
/* 顺序队列:BFS 需要用它实现“先发现的顶点先扩展”。 */
typedef struct {
int data[MAX_VERTEX_NUM];
int front;
int rear;
} SqQueue;
/* Kruskal 用的边结构:把邻接矩阵中的有效边提出来,后面统一按权值排序。 */
typedef struct {
int u;
int v;
int weight;
} Edge;
/* 初始化队列:front 和 rear 都回到 0,表示当前为空。 */
void InitQueue(SqQueue *queue) {
if (queue == NULL) {
return;
}
queue->front = 0;
queue->rear = 0;
}
/* 判断队列是否为空:front 和 rear 重合时表示没有元素。 */
bool IsQueueEmpty(const SqQueue *queue) {
return queue == NULL || queue->front == queue->rear;
}
/* 入队:把顶点下标压到队尾,供后续按 BFS 顺序处理。 */
bool Enqueue(SqQueue *queue, int value) {
int next_rear;
if (queue == NULL) {
return false;
}
next_rear = (queue->rear + 1) % MAX_VERTEX_NUM;
if (next_rear == queue->front) {
return false;
}
queue->data[queue->rear] = value;
queue->rear = next_rear;
return true;
}
/* 出队:取出当前队头顶点下标,并让 front 向后移动。 */
bool Dequeue(SqQueue *queue, int *value) {
if (queue == NULL || value == NULL || IsQueueEmpty(queue)) {
return false;
}
*value = queue->data[queue->front];
queue->front = (queue->front + 1) % MAX_VERTEX_NUM;
return true;
}
/* 初始化邻接矩阵:先清规模,再把矩阵设置成“无边”状态。 */
void InitAMGraph(AMGraph *graph, const char *vertex_names, bool directed) {
int i;
int j;
int length;
if (graph == NULL || vertex_names == NULL) {
return;
}
length = (int)strlen(vertex_names);
if (length <= 0 || length > MAX_VERTEX_NUM) {
return;
}
graph->vexnum = length;
graph->arcnum = 0;
graph->directed = directed;
for (i = 0; i < graph->vexnum; i++) {
graph->vexs[i] = vertex_names[i];
}
for (i = 0; i < graph->vexnum; i++) {
for (j = 0; j < graph->vexnum; j++) {
if (i == j) {
graph->edges[i][j] = 0;
} else {
graph->edges[i][j] = INF;
}
}
}
}
/* 按顶点名定位下标:后续加边和遍历都依赖这个映射。 */
int LocateVertexAM(const AMGraph *graph, char vertex) {
int i;
if (graph == NULL) {
return -1;
}
for (i = 0; i < graph->vexnum; i++) {
if (graph->vexs[i] == vertex) {
return i;
}
}
return -1;
}
/* 邻接矩阵加边:有向图只加一侧,无向图要对称补上另一侧。 */
bool AddEdgeAM(AMGraph *graph, char from, char to, int weight) {
int i;
int j;
if (graph == NULL || weight <= 0) {
return false;
}
i = LocateVertexAM(graph, from);
j = LocateVertexAM(graph, to);
if (i < 0 || j < 0 || i == j) {
return false;
}
if (graph->edges[i][j] == INF) {
graph->arcnum++;
}
graph->edges[i][j] = weight;
if (!graph->directed) {
graph->edges[j][i] = weight;
}
return true;
}
/* 打印邻接矩阵:便于把“图结构”和“矩阵内容”对应起来。 */
void PrintAMGraph(const AMGraph *graph) {
int i;
int j;
if (graph == NULL) {
return;
}
printf("Adjacency Matrix:\n ");
for (i = 0; i < graph->vexnum; i++) {
printf(" %c", graph->vexs[i]);
}
printf("\n");
for (i = 0; i < graph->vexnum; i++) {
printf(" %c ", graph->vexs[i]);
for (j = 0; j < graph->vexnum; j++) {
if (graph->edges[i][j] == INF) {
printf(" -");
} else {
printf(" %2d", graph->edges[i][j]);
}
}
printf("\n");
}
}
/* 创建邻接表边结点:把邻接点和权值封装起来。 */
ArcNode *CreateArcNode(int adjvex, int weight) {
ArcNode *node;
node = (ArcNode *)malloc(sizeof(ArcNode));
if (node == NULL) {
return NULL;
}
node->adjvex = adjvex;
node->weight = weight;
node->nextarc = NULL;
return node;
}
/* 初始化邻接表:先写顶点,再把每个顶点的第一条边指针置空。 */
void InitALGraph(ALGraph *graph, const char *vertex_names, bool directed) {
int i;
int length;
if (graph == NULL || vertex_names == NULL) {
return;
}
length = (int)strlen(vertex_names);
if (length <= 0 || length > MAX_VERTEX_NUM) {
return;
}
graph->vexnum = length;
graph->arcnum = 0;
graph->directed = directed;
for (i = 0; i < graph->vexnum; i++) {
graph->vertices[i].data = vertex_names[i];
graph->vertices[i].firstarc = NULL;
}
}
/* 按顶点名定位邻接表下标:和邻接矩阵版本保持相同思路。 */
int LocateVertexAL(const ALGraph *graph, char vertex) {
int i;
if (graph == NULL) {
return -1;
}
for (i = 0; i < graph->vexnum; i++) {
if (graph->vertices[i].data == vertex) {
return i;
}
}
return -1;
}
/* 头插法挂一条边:新边结点插到邻接表最前面。 */
bool AddArcNode(ALGraph *graph, int from, int to, int weight) {
ArcNode *node;
if (graph == NULL || from < 0 || from >= graph->vexnum || to < 0 || to >= graph->vexnum) {
return false;
}
node = CreateArcNode(to, weight);
if (node == NULL) {
return false;
}
node->nextarc = graph->vertices[from].firstarc;
graph->vertices[from].firstarc = node;
return true;
}
/* 邻接表加边:无向图要补两次,有向图只补一次。 */
bool AddEdgeAL(ALGraph *graph, char from, char to, int weight) {
int i;
int j;
if (graph == NULL || weight <= 0) {
return false;
}
i = LocateVertexAL(graph, from);
j = LocateVertexAL(graph, to);
if (i < 0 || j < 0 || i == j) {
return false;
}
if (!AddArcNode(graph, i, j, weight)) {
return false;
}
if (!graph->directed) {
if (!AddArcNode(graph, j, i, weight)) {
return false;
}
}
graph->arcnum++;
return true;
}
/* 打印邻接表:观察每个顶点后面都连了哪些邻接点。 */
void PrintALGraph(const ALGraph *graph) {
int i;
ArcNode *arc;
if (graph == NULL) {
return;
}
printf("Adjacency List:\n");
for (i = 0; i < graph->vexnum; i++) {
printf("%c -> ", graph->vertices[i].data);
arc = graph->vertices[i].firstarc;
while (arc != NULL) {
printf("(%c, w=%d) ", graph->vertices[arc->adjvex].data, arc->weight);
arc = arc->nextarc;
}
printf("^\n");
}
}
/* 释放邻接表:逐个顶点把边链表清掉,避免内存泄漏。 */
void DestroyALGraph(ALGraph *graph) {
int i;
ArcNode *current;
ArcNode *next;
if (graph == NULL) {
return;
}
for (i = 0; i < graph->vexnum; i++) {
current = graph->vertices[i].firstarc;
while (current != NULL) {
next = current->nextarc;
free(current);
current = next;
}
graph->vertices[i].firstarc = NULL;
}
}
/* 访问顶点:统一输出接口,后续遍历都复用它。 */
void VisitVertex(char vertex) {
printf("%c ", vertex);
}
/* 邻接矩阵版 DFS 递归函数:先访问当前顶点,再递归访问尚未访问的邻接点。 */
void DFSAMUtil(const AMGraph *graph, int v, bool visited[]) {
int w;
visited[v] = true;
VisitVertex(graph->vexs[v]);
for (w = 0; w < graph->vexnum; w++) {
if (!visited[w] && graph->edges[v][w] != INF && graph->edges[v][w] != 0) {
DFSAMUtil(graph, w, visited);
}
}
}
/* 邻接矩阵版 DFS:兼顾非连通图,必要时从新的连通分量重新出发。 */
void DFSAM(const AMGraph *graph) {
bool visited[MAX_VERTEX_NUM] = {false};
int i;
if (graph == NULL) {
return;
}
for (i = 0; i < graph->vexnum; i++) {
if (!visited[i]) {
DFSAMUtil(graph, i, visited);
}
}
}
/* 邻接矩阵版 BFS:先访问一个顶点,再按队列顺序逐层扩展。 */
void BFSAM(const AMGraph *graph) {
bool visited[MAX_VERTEX_NUM] = {false};
SqQueue queue;
int i;
int v;
int w;
if (graph == NULL) {
return;
}
InitQueue(&queue);
for (i = 0; i < graph->vexnum; i++) {
if (visited[i]) {
continue;
}
visited[i] = true;
VisitVertex(graph->vexs[i]);
Enqueue(&queue, i);
while (!IsQueueEmpty(&queue)) {
Dequeue(&queue, &v);
for (w = 0; w < graph->vexnum; w++) {
if (!visited[w] && graph->edges[v][w] != INF && graph->edges[v][w] != 0) {
visited[w] = true;
VisitVertex(graph->vexs[w]);
Enqueue(&queue, w);
}
}
}
}
}
/* 邻接表版 DFS 递归函数:顺着边链表把当前顶点能到的点一路走深。 */
void DFSALUtil(const ALGraph *graph, int v, bool visited[]) {
ArcNode *arc;
visited[v] = true;
VisitVertex(graph->vertices[v].data);
arc = graph->vertices[v].firstarc;
while (arc != NULL) {
if (!visited[arc->adjvex]) {
DFSALUtil(graph, arc->adjvex, visited);
}
arc = arc->nextarc;
}
}
/* 邻接表版 DFS:写法和矩阵版类似,只是邻接点获取方式不同。 */
void DFSAL(const ALGraph *graph) {
bool visited[MAX_VERTEX_NUM] = {false};
int i;
if (graph == NULL) {
return;
}
for (i = 0; i < graph->vexnum; i++) {
if (!visited[i]) {
DFSALUtil(graph, i, visited);
}
}
}
/* 邻接表版 BFS:队列逻辑不变,只是遍历邻接点时改成扫边链表。 */
void BFSAL(const ALGraph *graph) {
bool visited[MAX_VERTEX_NUM] = {false};
SqQueue queue;
ArcNode *arc;
int i;
int v;
if (graph == NULL) {
return;
}
InitQueue(&queue);
for (i = 0; i < graph->vexnum; i++) {
if (visited[i]) {
continue;
}
visited[i] = true;
VisitVertex(graph->vertices[i].data);
Enqueue(&queue, i);
while (!IsQueueEmpty(&queue)) {
Dequeue(&queue, &v);
arc = graph->vertices[v].firstarc;
while (arc != NULL) {
if (!visited[arc->adjvex]) {
visited[arc->adjvex] = true;
VisitVertex(graph->vertices[arc->adjvex].data);
Enqueue(&queue, arc->adjvex);
}
arc = arc->nextarc;
}
}
}
}
/* 只做标记不输出的 DFS:后面统计连通分量时更方便复用。 */
void DFSMarkAM(const AMGraph *graph, int v, bool visited[]) {
int w;
visited[v] = true;
for (w = 0; w < graph->vexnum; w++) {
if (!visited[w] && graph->edges[v][w] != INF && graph->edges[v][w] != 0) {
DFSMarkAM(graph, w, visited);
}
}
}
/* 统计无向图连通分量:每发现一个还没访问过的顶点,就说明找到一个新分量。 */
int CountConnectedComponentsAM(const AMGraph *graph) {
bool visited[MAX_VERTEX_NUM] = {false};
int components;
int i;
if (graph == NULL) {
return 0;
}
components = 0;
for (i = 0; i < graph->vexnum; i++) {
if (!visited[i]) {
components++;
DFSMarkAM(graph, i, visited);
}
}
return components;
}
/* 拓扑排序:不断取入度为 0 的顶点输出,并删除其发出的边。 */
bool TopologicalSortAL(const ALGraph *graph, char order[]) {
int indegree[MAX_VERTEX_NUM] = {0};
SqQueue queue;
ArcNode *arc;
int i;
int v;
int count;
if (graph == NULL || order == NULL) {
return false;
}
for (i = 0; i < graph->vexnum; i++) {
arc = graph->vertices[i].firstarc;
while (arc != NULL) {
indegree[arc->adjvex]++;
arc = arc->nextarc;
}
}
InitQueue(&queue);
for (i = 0; i < graph->vexnum; i++) {
if (indegree[i] == 0) {
Enqueue(&queue, i);
}
}
count = 0;
while (!IsQueueEmpty(&queue)) {
Dequeue(&queue, &v);
order[count++] = graph->vertices[v].data;
arc = graph->vertices[v].firstarc;
while (arc != NULL) {
indegree[arc->adjvex]--;
if (indegree[arc->adjvex] == 0) {
Enqueue(&queue, arc->adjvex);
}
arc = arc->nextarc;
}
}
order[count] = '\0';
return count == graph->vexnum;
}
/* 求并查集根结点:一路向上找代表元,并顺手做路径压缩。 */
int FindSet(int parent[], int x) {
if (parent[x] != x) {
parent[x] = FindSet(parent, parent[x]);
}
return parent[x];
}
/* 合并两个集合:把秩较小的树挂到秩较大的树下面,减少后续查找高度。 */
void UnionSet(int parent[], int rank[], int x, int y) {
int root_x;
int root_y;
root_x = FindSet(parent, x);
root_y = FindSet(parent, y);
if (root_x == root_y) {
return;
}
if (rank[root_x] < rank[root_y]) {
parent[root_x] = root_y;
} else if (rank[root_x] > rank[root_y]) {
parent[root_y] = root_x;
} else {
parent[root_y] = root_x;
rank[root_x]++;
}
}
/* 给 qsort 用的比较函数:边权更小的边排在前面,方便 Kruskal 逐条尝试。 */
int CompareEdgeByWeight(const void *lhs, const void *rhs) {
const Edge *left;
const Edge *right;
left = (const Edge *)lhs;
right = (const Edge *)rhs;
return left->weight - right->weight;
}
/* Kruskal 算法:把所有边按权值从小到大尝试,能接且不成环就选中。 */
int KruskalMSTWeightAM(const AMGraph *graph) {
Edge edges[MAX_VERTEX_NUM * MAX_VERTEX_NUM];
int parent[MAX_VERTEX_NUM];
int rank[MAX_VERTEX_NUM] = {0};
int edge_count;
int selected_edges;
int total_weight;
int i;
int j;
if (graph == NULL || graph->directed || graph->vexnum == 0) {
return -1;
}
edge_count = 0;
for (i = 0; i < graph->vexnum; i++) {
parent[i] = i;
for (j = i + 1; j < graph->vexnum; j++) {
if (graph->edges[i][j] != INF && graph->edges[i][j] != 0) {
edges[edge_count].u = i;
edges[edge_count].v = j;
edges[edge_count].weight = graph->edges[i][j];
edge_count++;
}
}
}
qsort(edges, edge_count, sizeof(Edge), CompareEdgeByWeight);
total_weight = 0;
selected_edges = 0;
for (i = 0; i < edge_count && selected_edges < graph->vexnum - 1; i++) {
if (FindSet(parent, edges[i].u) != FindSet(parent, edges[i].v)) {
UnionSet(parent, rank, edges[i].u, edges[i].v);
total_weight += edges[i].weight;
selected_edges++;
}
}
if (selected_edges != graph->vexnum - 1) {
return -1;
}
return total_weight;
}
/* Prim 算法求最小生成树权值:每次把当前生成树到外部的最短边接进来。 */
int PrimMSTWeightAM(const AMGraph *graph, int start) {
int lowcost[MAX_VERTEX_NUM];
bool in_tree[MAX_VERTEX_NUM] = {false};
int i;
int j;
int min_cost;
int next_vertex;
int total_weight;
if (graph == NULL || start < 0 || start >= graph->vexnum || graph->vexnum == 0) {
return -1;
}
for (i = 0; i < graph->vexnum; i++) {
lowcost[i] = graph->edges[start][i];
}
in_tree[start] = true;
total_weight = 0;
for (i = 1; i < graph->vexnum; i++) {
min_cost = INF;
next_vertex = -1;
for (j = 0; j < graph->vexnum; j++) {
if (!in_tree[j] && lowcost[j] < min_cost) {
min_cost = lowcost[j];
next_vertex = j;
}
}
if (next_vertex == -1) {
return -1;
}
in_tree[next_vertex] = true;
total_weight += min_cost;
for (j = 0; j < graph->vexnum; j++) {
if (!in_tree[j] && graph->edges[next_vertex][j] < lowcost[j]) {
lowcost[j] = graph->edges[next_vertex][j];
}
}
}
return total_weight;
}
/* Floyd 算法:允许每个顶点依次作为中转点,不断改进任意两点间的最短路。 */
void FloydAM(const AMGraph *graph, int dist[][MAX_VERTEX_NUM], int path[][MAX_VERTEX_NUM]) {
int i;
int j;
int k;
if (graph == NULL || dist == NULL || path == NULL) {
return;
}
for (i = 0; i < graph->vexnum; i++) {
for (j = 0; j < graph->vexnum; j++) {
dist[i][j] = graph->edges[i][j];
if (i != j && graph->edges[i][j] != INF) {
path[i][j] = j;
} else {
path[i][j] = -1;
}
}
}
for (k = 0; k < graph->vexnum; k++) {
for (i = 0; i < graph->vexnum; i++) {
for (j = 0; j < graph->vexnum; j++) {
if (dist[i][k] == INF || dist[k][j] == INF) {
continue;
}
if (dist[i][k] + dist[k][j] < dist[i][j]) {
dist[i][j] = dist[i][k] + dist[k][j];
path[i][j] = path[i][k];
}
}
}
}
}
/* 打印 Floyd 距离矩阵:便于一次性观察任意两点间的最短路径长度。 */
void PrintFloydDistances(const AMGraph *graph, int dist[][MAX_VERTEX_NUM]) {
int i;
int j;
if (graph == NULL || dist == NULL) {
return;
}
printf("Floyd distance matrix:\n ");
for (i = 0; i < graph->vexnum; i++) {
printf(" %c", graph->vexs[i]);
}
printf("\n");
for (i = 0; i < graph->vexnum; i++) {
printf(" %c ", graph->vexs[i]);
for (j = 0; j < graph->vexnum; j++) {
if (dist[i][j] == INF) {
printf(" -");
} else {
printf(" %2d", dist[i][j]);
}
}
printf("\n");
}
}
/* 打印 Floyd 还原出的具体路径:沿着 path 数组记录的“下一跳”一路走到终点。 */
void PrintFloydPathAM(const AMGraph *graph, int path[][MAX_VERTEX_NUM], int from, int to) {
int current;
if (graph == NULL || path == NULL || from < 0 || to < 0 ||
from >= graph->vexnum || to >= graph->vexnum) {
return;
}
if (from == to) {
printf("%c\n", graph->vexs[from]);
return;
}
if (path[from][to] == -1) {
printf("No path\n");
return;
}
current = from;
printf("%c", graph->vexs[current]);
while (current != to) {
current = path[current][to];
if (current == -1) {
printf(" -> ?\n");
return;
}
printf(" -> %c", graph->vexs[current]);
}
printf("\n");
}
/* Dijkstra 单源最短路径:dist 记录当前最短估计,finalized 记录顶点是否已确定最短路。 */
void DijkstraAM(const AMGraph *graph, int source, int dist[], int path[]) {
bool finalized[MAX_VERTEX_NUM] = {false};
int i;
int j;
int min_dist;
int u;
if (graph == NULL || dist == NULL || path == NULL || source < 0 || source >= graph->vexnum) {
return;
}
for (i = 0; i < graph->vexnum; i++) {
dist[i] = graph->edges[source][i];
if (i != source && graph->edges[source][i] != INF) {
path[i] = source;
} else {
path[i] = -1;
}
}
dist[source] = 0;
finalized[source] = true;
for (i = 1; i < graph->vexnum; i++) {
min_dist = INF;
u = -1;
for (j = 0; j < graph->vexnum; j++) {
if (!finalized[j] && dist[j] < min_dist) {
min_dist = dist[j];
u = j;
}
}
if (u == -1) {
break;
}
finalized[u] = true;
for (j = 0; j < graph->vexnum; j++) {
if (!finalized[j] &&
graph->edges[u][j] != INF &&
dist[u] != INF &&
dist[u] + graph->edges[u][j] < dist[j]) {
dist[j] = dist[u] + graph->edges[u][j];
path[j] = u;
}
}
}
}
/* 打印 Dijkstra 结果:便于把每个顶点的最短路长度直接看出来。 */
void PrintDijkstraResult(const AMGraph *graph, int source, const int dist[]) {
int i;
if (graph == NULL || dist == NULL) {
return;
}
printf("Dijkstra distances from %c: ", graph->vexs[source]);
for (i = 0; i < graph->vexnum; i++) {
if (dist[i] == INF) {
printf("%c=INF ", graph->vexs[i]);
} else {
printf("%c=%d ", graph->vexs[i], dist[i]);
}
}
printf("\n");
}
/* 生成拓扑序下标:关键路径既要正推最早时间,也要逆推最迟时间,所以先保留顺序。 */
bool GetTopologicalOrderAL(const ALGraph *graph, int order[], int *count) {
int indegree[MAX_VERTEX_NUM] = {0};
SqQueue queue;
ArcNode *arc;
int i;
int v;
int total;
if (graph == NULL || order == NULL || count == NULL) {
return false;
}
for (i = 0; i < graph->vexnum; i++) {
arc = graph->vertices[i].firstarc;
while (arc != NULL) {
indegree[arc->adjvex]++;
arc = arc->nextarc;
}
}
InitQueue(&queue);
for (i = 0; i < graph->vexnum; i++) {
if (indegree[i] == 0) {
Enqueue(&queue, i);
}
}
total = 0;
while (!IsQueueEmpty(&queue)) {
Dequeue(&queue, &v);
order[total++] = v;
arc = graph->vertices[v].firstarc;
while (arc != NULL) {
indegree[arc->adjvex]--;
if (indegree[arc->adjvex] == 0) {
Enqueue(&queue, arc->adjvex);
}
arc = arc->nextarc;
}
}
*count = total;
return total == graph->vexnum;
}
/* 关键路径:先正推事件最早发生时间,再逆推最迟发生时间,最后找时差为 0 的活动。 */
bool CriticalPathAL(const ALGraph *graph,
int ve[],
int vl[],
bool critical[][MAX_VERTEX_NUM],
int *critical_length) {
int order[MAX_VERTEX_NUM];
int count;
ArcNode *arc;
int i;
int v;
int ee;
int el;
int project_length;
if (graph == NULL || ve == NULL || vl == NULL || critical == NULL || critical_length == NULL) {
return false;
}
if (!GetTopologicalOrderAL(graph, order, &count)) {
return false;
}
for (i = 0; i < graph->vexnum; i++) {
ve[i] = 0;
for (v = 0; v < graph->vexnum; v++) {
critical[i][v] = false;
}
}
for (i = 0; i < count; i++) {
v = order[i];
arc = graph->vertices[v].firstarc;
while (arc != NULL) {
if (ve[v] + arc->weight > ve[arc->adjvex]) {
ve[arc->adjvex] = ve[v] + arc->weight;
}
arc = arc->nextarc;
}
}
project_length = 0;
for (i = 0; i < graph->vexnum; i++) {
if (ve[i] > project_length) {
project_length = ve[i];
}
vl[i] = project_length;
}
for (i = count - 1; i >= 0; i--) {
v = order[i];
arc = graph->vertices[v].firstarc;
while (arc != NULL) {
if (vl[arc->adjvex] - arc->weight < vl[v]) {
vl[v] = vl[arc->adjvex] - arc->weight;
}
arc = arc->nextarc;
}
}
for (v = 0; v < graph->vexnum; v++) {
arc = graph->vertices[v].firstarc;
while (arc != NULL) {
ee = ve[v];
el = vl[arc->adjvex] - arc->weight;
if (ee == el) {
critical[v][arc->adjvex] = true;
}
arc = arc->nextarc;
}
}
*critical_length = project_length;
return true;
}
/* 打印关键路径结果:先输出 ve/vl,再列出关键活动,方便把表和图对应起来。 */
void PrintCriticalPathResult(const ALGraph *graph,
const int ve[],
const int vl[],
bool critical[][MAX_VERTEX_NUM],
int critical_length) {
ArcNode *arc;
int i;
if (graph == NULL || ve == NULL || vl == NULL || critical == NULL) {
return;
}
printf("Critical path project length: %d\n", critical_length);
printf("ve: ");
for (i = 0; i < graph->vexnum; i++) {
printf("%c=%d ", graph->vertices[i].data, ve[i]);
}
printf("\n");
printf("vl: ");
for (i = 0; i < graph->vexnum; i++) {
printf("%c=%d ", graph->vertices[i].data, vl[i]);
}
printf("\n");
printf("Critical activities: ");
for (i = 0; i < graph->vexnum; i++) {
arc = graph->vertices[i].firstarc;
while (arc != NULL) {
if (critical[i][arc->adjvex]) {
printf("<%c,%c> ", graph->vertices[i].data, graph->vertices[arc->adjvex].data);
}
arc = arc->nextarc;
}
}
printf("\n");
}
/* 构造一张示例无向图:后面统一用它演示矩阵、邻接表、DFS、BFS。 */
void BuildSampleGraphs(AMGraph *matrix_graph, ALGraph *list_graph) {
const char *vertices = "ABCDE";
InitAMGraph(matrix_graph, vertices, false);
InitALGraph(list_graph, vertices, false);
AddEdgeAM(matrix_graph, 'A', 'B', 1);
AddEdgeAM(matrix_graph, 'A', 'C', 1);
AddEdgeAM(matrix_graph, 'B', 'D', 1);
AddEdgeAM(matrix_graph, 'C', 'D', 1);
AddEdgeAM(matrix_graph, 'C', 'E', 1);
AddEdgeAL(list_graph, 'A', 'B', 1);
AddEdgeAL(list_graph, 'A', 'C', 1);
AddEdgeAL(list_graph, 'B', 'D', 1);
AddEdgeAL(list_graph, 'C', 'D', 1);
AddEdgeAL(list_graph, 'C', 'E', 1);
}
/* 构造示例 DAG:后面用它演示拓扑排序。 */
void BuildSampleDAG(ALGraph *dag) {
const char *vertices = "ABCDEF";
InitALGraph(dag, vertices, true);
AddEdgeAL(dag, 'A', 'C', 1);
AddEdgeAL(dag, 'A', 'D', 1);
AddEdgeAL(dag, 'B', 'D', 1);
AddEdgeAL(dag, 'C', 'E', 1);
AddEdgeAL(dag, 'D', 'E', 1);
AddEdgeAL(dag, 'E', 'F', 1);
}
/* 构造示例带权无向图:后面用它演示 Prim 最小生成树。 */
void BuildSampleWeightedUndirectedGraph(AMGraph *graph) {
const char *vertices = "ABCDEF";
InitAMGraph(graph, vertices, false);
AddEdgeAM(graph, 'A', 'B', 6);
AddEdgeAM(graph, 'A', 'C', 1);
AddEdgeAM(graph, 'A', 'D', 5);
AddEdgeAM(graph, 'B', 'C', 5);
AddEdgeAM(graph, 'B', 'E', 3);
AddEdgeAM(graph, 'C', 'D', 5);
AddEdgeAM(graph, 'C', 'E', 6);
AddEdgeAM(graph, 'C', 'F', 4);
AddEdgeAM(graph, 'D', 'F', 2);
AddEdgeAM(graph, 'E', 'F', 6);
}
/* 构造示例带权有向图:后面用它演示 Dijkstra 单源最短路径。 */
void BuildSampleWeightedDirectedGraph(AMGraph *graph) {
const char *vertices = "ABCDE";
InitAMGraph(graph, vertices, true);
AddEdgeAM(graph, 'A', 'B', 10);
AddEdgeAM(graph, 'A', 'C', 3);
AddEdgeAM(graph, 'B', 'C', 1);
AddEdgeAM(graph, 'B', 'D', 2);
AddEdgeAM(graph, 'C', 'B', 4);
AddEdgeAM(graph, 'C', 'D', 8);
AddEdgeAM(graph, 'C', 'E', 2);
AddEdgeAM(graph, 'D', 'E', 7);
AddEdgeAM(graph, 'E', 'D', 9);
}
/* 构造示例 AOE 网:后面用它演示关键路径的 ve、vl 和关键活动。 */
void BuildSampleAOEGraph(ALGraph *graph) {
const char *vertices = "ABCDEFG";
InitALGraph(graph, vertices, true);
AddEdgeAL(graph, 'A', 'B', 3);
AddEdgeAL(graph, 'A', 'C', 2);
AddEdgeAL(graph, 'B', 'D', 2);
AddEdgeAL(graph, 'B', 'E', 3);
AddEdgeAL(graph, 'C', 'D', 4);
AddEdgeAL(graph, 'C', 'F', 3);
AddEdgeAL(graph, 'D', 'G', 2);
AddEdgeAL(graph, 'E', 'G', 3);
AddEdgeAL(graph, 'F', 'G', 2);
}
int main(void) {
AMGraph matrix_graph;
AMGraph weighted_graph;
AMGraph shortest_path_graph;
ALGraph list_graph;
ALGraph dag;
ALGraph aoe_graph;
char topo_order[MAX_VERTEX_NUM + 1];
int dist[MAX_VERTEX_NUM];
int floyd_dist[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
int floyd_path[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
int path[MAX_VERTEX_NUM];
int ve[MAX_VERTEX_NUM];
int vl[MAX_VERTEX_NUM];
bool critical[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
int critical_length;
BuildSampleGraphs(&matrix_graph, &list_graph);
PrintAMGraph(&matrix_graph);
printf("\n");
PrintALGraph(&list_graph);
printf("\n");
printf("DFS by adjacency matrix: ");
DFSAM(&matrix_graph);
printf("\n");
printf("BFS by adjacency matrix: ");
BFSAM(&matrix_graph);
printf("\n");
printf("DFS by adjacency list: ");
DFSAL(&list_graph);
printf("\n");
printf("BFS by adjacency list: ");
BFSAL(&list_graph);
printf("\n");
printf("Connected components in sample undirected graph: %d\n",
CountConnectedComponentsAM(&matrix_graph));
BuildSampleDAG(&dag);
if (TopologicalSortAL(&dag, topo_order)) {
printf("Topological order: %s\n", topo_order);
} else {
printf("Topological order: graph has a cycle\n");
}
BuildSampleWeightedUndirectedGraph(&weighted_graph);
printf("Prim MST total weight: %d\n", PrimMSTWeightAM(&weighted_graph, 0));
printf("Kruskal MST total weight: %d\n", KruskalMSTWeightAM(&weighted_graph));
BuildSampleWeightedDirectedGraph(&shortest_path_graph);
DijkstraAM(&shortest_path_graph, 0, dist, path);
PrintDijkstraResult(&shortest_path_graph, 0, dist);
FloydAM(&shortest_path_graph, floyd_dist, floyd_path);
PrintFloydDistances(&shortest_path_graph, floyd_dist);
printf("Floyd path A -> D: ");
PrintFloydPathAM(&shortest_path_graph, floyd_path, 0, 3);
printf("Floyd path A -> E: ");
PrintFloydPathAM(&shortest_path_graph, floyd_path, 0, 4);
BuildSampleAOEGraph(&aoe_graph);
if (CriticalPathAL(&aoe_graph, ve, vl, critical, &critical_length)) {
PrintCriticalPathResult(&aoe_graph, ve, vl, critical, critical_length);
} else {
printf("Critical path: graph has a cycle\n");
}
DestroyALGraph(&aoe_graph);
DestroyALGraph(&dag);
DestroyALGraph(&list_graph);
return 0;
}
逐行注释版
/* 绗?{number}琛岋細寮曞叆褰撳墠婧愮爜鍚庨潰浼氱敤鍒扮殑澶存枃浠躲€?*/
#include <stdbool.h>
/* 绗?{number}琛岋細寮曞叆褰撳墠婧愮爜鍚庨潰浼氱敤鍒扮殑澶存枃浠躲€?*/
#include <stdio.h>
/* 绗?{number}琛岋細寮曞叆褰撳墠婧愮爜鍚庨潰浼氱敤鍒扮殑澶存枃浠躲€?*/
#include <stdlib.h>
/* 绗?{number}琛岋細寮曞叆褰撳墠婧愮爜鍚庨潰浼氱敤鍒扮殑澶存枃浠躲€?*/
#include <string.h>
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細瀹氫箟鍚庨潰瑕佸弽澶嶄娇鐢ㄧ殑瀹忓父閲忋€?*/
#define MAX_VERTEX_NUM 20
/* 绗?{number}琛岋細瀹氫箟鍚庨潰瑕佸弽澶嶄娇鐢ㄧ殑瀹忓父閲忋€?*/
#define INF 1000000000
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細杩欐槸鍘熸簮鐮侀噷宸茬粡瀛樺湪鐨勮鏄庢€ф敞閲娿€?*/
/* 邻接矩阵图结构:vexs 保存顶点名,edges 保存边权,vexnum/arcnum 记录规模。 */
/* 绗?{number}琛岋細寮€濮嬪畾涔変竴涓粨鏋勪綋绫诲瀷锛岀敤鏉ョ粍缁囩浉鍏虫暟鎹€?*/
typedef struct {
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
char vexs[MAX_VERTEX_NUM];
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
int edges[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
int vexnum;
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
int arcnum;
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
bool directed;
/* 绗?{number}琛岋細鎵ц杩欎竴琛屼唬鐮侊紝缁х画鎺ㄨ繘褰撳墠閫昏緫銆?*/
} AMGraph;
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細杩欐槸鍘熸簮鐮侀噷宸茬粡瀛樺湪鐨勮鏄庢€ф敞閲娿€?*/
/* 邻接表边结点:adjvex 是邻接点下标,weight 是边权,nextarc 指向下一条边。 */
/* 绗?{number}琛岋細寮€濮嬪畾涔変竴涓粨鏋勪綋绫诲瀷锛岀敤鏉ョ粍缁囩浉鍏虫暟鎹€?*/
typedef struct ArcNode {
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
int adjvex;
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
int weight;
/* 绗?{number}琛岋細鎵ц杩欎竴琛屼唬鐮侊紝缁х画鎺ㄨ繘褰撳墠閫昏緫銆?*/
struct ArcNode *nextarc;
/* 绗?{number}琛岋細鎵ц杩欎竴琛屼唬鐮侊紝缁х画鎺ㄨ繘褰撳墠閫昏緫銆?*/
} ArcNode;
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細杩欐槸鍘熸簮鐮侀噷宸茬粡瀛樺湪鐨勮鏄庢€ф敞閲娿€?*/
/* 邻接表顶点结点:data 保存顶点名,firstarc 指向第一条出边。 */
/* 绗?{number}琛岋細寮€濮嬪畾涔変竴涓粨鏋勪綋绫诲瀷锛岀敤鏉ョ粍缁囩浉鍏虫暟鎹€?*/
typedef struct {
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
char data;
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
ArcNode *firstarc;
/* 绗?{number}琛岋細鎵ц杩欎竴琛屼唬鐮侊紝缁х画鎺ㄨ繘褰撳墠閫昏緫銆?*/
} VNode;
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細杩欐槸鍘熸簮鐮侀噷宸茬粡瀛樺湪鐨勮鏄庢€ф敞閲娿€?*/
/* 邻接表图结构:vertices 保存所有顶点,vexnum/arcnum 记录规模。 */
/* 绗?{number}琛岋細寮€濮嬪畾涔変竴涓粨鏋勪綋绫诲瀷锛岀敤鏉ョ粍缁囩浉鍏虫暟鎹€?*/
typedef struct {
/* 绗?{number}琛岋細鎵ц杩欎竴琛屼唬鐮侊紝缁х画鎺ㄨ繘褰撳墠閫昏緫銆?*/
VNode vertices[MAX_VERTEX_NUM];
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
int vexnum;
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
int arcnum;
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
bool directed;
/* 绗?{number}琛岋細鎵ц杩欎竴琛屼唬鐮侊紝缁х画鎺ㄨ繘褰撳墠閫昏緫銆?*/
} ALGraph;
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細杩欐槸鍘熸簮鐮侀噷宸茬粡瀛樺湪鐨勮鏄庢€ф敞閲娿€?*/
/* 顺序队列:BFS 需要用它实现“先发现的顶点先扩展”。 */
/* 绗?{number}琛岋細寮€濮嬪畾涔変竴涓粨鏋勪綋绫诲瀷锛岀敤鏉ョ粍缁囩浉鍏虫暟鎹€?*/
typedef struct {
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
int data[MAX_VERTEX_NUM];
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
int front;
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
int rear;
/* 绗?{number}琛岋細鎵ц杩欎竴琛屼唬鐮侊紝缁х画鎺ㄨ繘褰撳墠閫昏緫銆?*/
} SqQueue;
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細杩欐槸鍘熸簮鐮侀噷宸茬粡瀛樺湪鐨勮鏄庢€ф敞閲娿€?*/
/* Kruskal 用的边结构:把邻接矩阵中的有效边提出来,后面统一按权值排序。 */
/* 绗?{number}琛岋細寮€濮嬪畾涔変竴涓粨鏋勪綋绫诲瀷锛岀敤鏉ョ粍缁囩浉鍏虫暟鎹€?*/
typedef struct {
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
int u;
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
int v;
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
int weight;
/* 绗?{number}琛岋細鎵ц杩欎竴琛屼唬鐮侊紝缁х画鎺ㄨ繘褰撳墠閫昏緫銆?*/
} Edge;
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細杩欐槸鍘熸簮鐮侀噷宸茬粡瀛樺湪鐨勮鏄庢€ф敞閲娿€?*/
/* 初始化队列:front 和 rear 都回到 0,表示当前为空。 */
/* 绗?{number}琛岋細瀹氫箟鍑芥暟 ㈠紑濮嬪啓瀹冪殑鍏蜂綋瀹炵幇銆?*/
void InitQueue(SqQueue *queue) {
/* 绗?{number}琛岋細杩涜鏉′欢鍒ゆ柇锛屽喅瀹氬綋鍓嶆祦绋嬭蛋鍝釜鍒嗘敮銆?*/
if (queue == NULL) {
/* 绗?{number}琛岋細鎶婂綋鍓嶅嚱鏁扮殑缁撴灉杩斿洖缁欒皟鐢ㄨ€咃紝骞剁粨鏉熷綋鍓嶅嚱鏁般€?*/
return;
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
queue->front = 0;
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
queue->rear = 0;
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細杩欐槸鍘熸簮鐮侀噷宸茬粡瀛樺湪鐨勮鏄庢€ф敞閲娿€?*/
/* 判断队列是否为空:front 和 rear 重合时表示没有元素。 */
/* 绗?{number}琛岋細瀹氫箟鍑芥暟 ㈠紑濮嬪啓瀹冪殑鍏蜂綋瀹炵幇銆?*/
bool IsQueueEmpty(const SqQueue *queue) {
/* 绗?{number}琛岋細鎶婂綋鍓嶅嚱鏁扮殑缁撴灉杩斿洖缁欒皟鐢ㄨ€咃紝骞剁粨鏉熷綋鍓嶅嚱鏁般€?*/
return queue == NULL || queue->front == queue->rear;
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細杩欐槸鍘熸簮鐮侀噷宸茬粡瀛樺湪鐨勮鏄庢€ф敞閲娿€?*/
/* 入队:把顶点下标压到队尾,供后续按 BFS 顺序处理。 */
/* 绗?{number}琛岋細瀹氫箟鍑芥暟 ㈠紑濮嬪啓瀹冪殑鍏蜂綋瀹炵幇銆?*/
bool Enqueue(SqQueue *queue, int value) {
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
int next_rear;
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細杩涜鏉′欢鍒ゆ柇锛屽喅瀹氬綋鍓嶆祦绋嬭蛋鍝釜鍒嗘敮銆?*/
if (queue == NULL) {
/* 绗?{number}琛岋細鎶婂綋鍓嶅嚱鏁扮殑缁撴灉杩斿洖缁欒皟鐢ㄨ€咃紝骞剁粨鏉熷綋鍓嶅嚱鏁般€?*/
return false;
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
next_rear = (queue->rear + 1) % MAX_VERTEX_NUM;
/* 绗?{number}琛岋細杩涜鏉′欢鍒ゆ柇锛屽喅瀹氬綋鍓嶆祦绋嬭蛋鍝釜鍒嗘敮銆?*/
if (next_rear == queue->front) {
/* 绗?{number}琛岋細鎶婂綋鍓嶅嚱鏁扮殑缁撴灉杩斿洖缁欒皟鐢ㄨ€咃紝骞剁粨鏉熷綋鍓嶅嚱鏁般€?*/
return false;
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
queue->data[queue->rear] = value;
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
queue->rear = next_rear;
/* 绗?{number}琛岋細鎶婂綋鍓嶅嚱鏁扮殑缁撴灉杩斿洖缁欒皟鐢ㄨ€咃紝骞剁粨鏉熷綋鍓嶅嚱鏁般€?*/
return true;
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細杩欐槸鍘熸簮鐮侀噷宸茬粡瀛樺湪鐨勮鏄庢€ф敞閲娿€?*/
/* 出队:取出当前队头顶点下标,并让 front 向后移动。 */
/* 绗?{number}琛岋細瀹氫箟鍑芥暟 ㈠紑濮嬪啓瀹冪殑鍏蜂綋瀹炵幇銆?*/
bool Dequeue(SqQueue *queue, int *value) {
/* 绗?{number}琛岋細杩涜鏉′欢鍒ゆ柇锛屽喅瀹氬綋鍓嶆祦绋嬭蛋鍝釜鍒嗘敮銆?*/
if (queue == NULL || value == NULL || IsQueueEmpty(queue)) {
/* 绗?{number}琛岋細鎶婂綋鍓嶅嚱鏁扮殑缁撴灉杩斿洖缁欒皟鐢ㄨ€咃紝骞剁粨鏉熷綋鍓嶅嚱鏁般€?*/
return false;
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
*value = queue->data[queue->front];
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
queue->front = (queue->front + 1) % MAX_VERTEX_NUM;
/* 绗?{number}琛岋細鎶婂綋鍓嶅嚱鏁扮殑缁撴灉杩斿洖缁欒皟鐢ㄨ€咃紝骞剁粨鏉熷綋鍓嶅嚱鏁般€?*/
return true;
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細杩欐槸鍘熸簮鐮侀噷宸茬粡瀛樺湪鐨勮鏄庢€ф敞閲娿€?*/
/* 初始化邻接矩阵:先清规模,再把矩阵设置成“无边”状态。 */
/* 绗?{number}琛岋細瀹氫箟鍑芥暟 ㈠紑濮嬪啓瀹冪殑鍏蜂綋瀹炵幇銆?*/
void InitAMGraph(AMGraph *graph, const char *vertex_names, bool directed) {
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
int i;
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
int j;
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
int length;
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細杩涜鏉′欢鍒ゆ柇锛屽喅瀹氬綋鍓嶆祦绋嬭蛋鍝釜鍒嗘敮銆?*/
if (graph == NULL || vertex_names == NULL) {
/* 绗?{number}琛岋細鎶婂綋鍓嶅嚱鏁扮殑缁撴灉杩斿洖缁欒皟鐢ㄨ€咃紝骞剁粨鏉熷綋鍓嶅嚱鏁般€?*/
return;
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
length = (int)strlen(vertex_names);
/* 绗?{number}琛岋細杩涜鏉′欢鍒ゆ柇锛屽喅瀹氬綋鍓嶆祦绋嬭蛋鍝釜鍒嗘敮銆?*/
if (length <= 0 || length > MAX_VERTEX_NUM) {
/* 绗?{number}琛岋細鎶婂綋鍓嶅嚱鏁扮殑缁撴灉杩斿洖缁欒皟鐢ㄨ€咃紝骞剁粨鏉熷綋鍓嶅嚱鏁般€?*/
return;
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
graph->vexnum = length;
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
graph->arcnum = 0;
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
graph->directed = directed;
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細寮€濮嬩竴娆?for 寰幆锛屾寜鍥哄畾娆℃暟閲嶅鎵ц鍚庨潰鐨勮鍙ャ€?*/
for (i = 0; i < graph->vexnum; i++) {
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
graph->vexs[i] = vertex_names[i];
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細寮€濮嬩竴娆?for 寰幆锛屾寜鍥哄畾娆℃暟閲嶅鎵ц鍚庨潰鐨勮鍙ャ€?*/
for (i = 0; i < graph->vexnum; i++) {
/* 绗?{number}琛岋細寮€濮嬩竴娆?for 寰幆锛屾寜鍥哄畾娆℃暟閲嶅鎵ц鍚庨潰鐨勮鍙ャ€?*/
for (j = 0; j < graph->vexnum; j++) {
/* 绗?{number}琛岋細杩涜鏉′欢鍒ゆ柇锛屽喅瀹氬綋鍓嶆祦绋嬭蛋鍝釜鍒嗘敮銆?*/
if (i == j) {
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
graph->edges[i][j] = 0;
/* 绗?{number}琛岋細鎵ц杩欎竴琛屼唬鐮侊紝缁х画鎺ㄨ繘褰撳墠閫昏緫銆?*/
} else {
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
graph->edges[i][j] = INF;
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細杩欐槸鍘熸簮鐮侀噷宸茬粡瀛樺湪鐨勮鏄庢€ф敞閲娿€?*/
/* 按顶点名定位下标:后续加边和遍历都依赖这个映射。 */
/* 绗?{number}琛岋細瀹氫箟鍑芥暟 ㈠紑濮嬪啓瀹冪殑鍏蜂綋瀹炵幇銆?*/
int LocateVertexAM(const AMGraph *graph, char vertex) {
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
int i;
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細杩涜鏉′欢鍒ゆ柇锛屽喅瀹氬綋鍓嶆祦绋嬭蛋鍝釜鍒嗘敮銆?*/
if (graph == NULL) {
/* 绗?{number}琛岋細鎶婂綋鍓嶅嚱鏁扮殑缁撴灉杩斿洖缁欒皟鐢ㄨ€咃紝骞剁粨鏉熷綋鍓嶅嚱鏁般€?*/
return -1;
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細寮€濮嬩竴娆?for 寰幆锛屾寜鍥哄畾娆℃暟閲嶅鎵ц鍚庨潰鐨勮鍙ャ€?*/
for (i = 0; i < graph->vexnum; i++) {
/* 绗?{number}琛岋細杩涜鏉′欢鍒ゆ柇锛屽喅瀹氬綋鍓嶆祦绋嬭蛋鍝釜鍒嗘敮銆?*/
if (graph->vexs[i] == vertex) {
/* 绗?{number}琛岋細鎶婂綋鍓嶅嚱鏁扮殑缁撴灉杩斿洖缁欒皟鐢ㄨ€咃紝骞剁粨鏉熷綋鍓嶅嚱鏁般€?*/
return i;
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細鎶婂綋鍓嶅嚱鏁扮殑缁撴灉杩斿洖缁欒皟鐢ㄨ€咃紝骞剁粨鏉熷綋鍓嶅嚱鏁般€?*/
return -1;
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細杩欐槸鍘熸簮鐮侀噷宸茬粡瀛樺湪鐨勮鏄庢€ф敞閲娿€?*/
/* 邻接矩阵加边:有向图只加一侧,无向图要对称补上另一侧。 */
/* 绗?{number}琛岋細瀹氫箟鍑芥暟 ㈠紑濮嬪啓瀹冪殑鍏蜂綋瀹炵幇銆?*/
bool AddEdgeAM(AMGraph *graph, char from, char to, int weight) {
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
int i;
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
int j;
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細杩涜鏉′欢鍒ゆ柇锛屽喅瀹氬綋鍓嶆祦绋嬭蛋鍝釜鍒嗘敮銆?*/
if (graph == NULL || weight <= 0) {
/* 绗?{number}琛岋細鎶婂綋鍓嶅嚱鏁扮殑缁撴灉杩斿洖缁欒皟鐢ㄨ€咃紝骞剁粨鏉熷綋鍓嶅嚱鏁般€?*/
return false;
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
i = LocateVertexAM(graph, from);
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
j = LocateVertexAM(graph, to);
/* 绗?{number}琛岋細杩涜鏉′欢鍒ゆ柇锛屽喅瀹氬綋鍓嶆祦绋嬭蛋鍝釜鍒嗘敮銆?*/
if (i < 0 || j < 0 || i == j) {
/* 绗?{number}琛岋細鎶婂綋鍓嶅嚱鏁扮殑缁撴灉杩斿洖缁欒皟鐢ㄨ€咃紝骞剁粨鏉熷綋鍓嶅嚱鏁般€?*/
return false;
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細杩涜鏉′欢鍒ゆ柇锛屽喅瀹氬綋鍓嶆祦绋嬭蛋鍝釜鍒嗘敮銆?*/
if (graph->edges[i][j] == INF) {
/* 绗?{number}琛岋細鎵ц杩欎竴琛屼唬鐮侊紝缁х画鎺ㄨ繘褰撳墠閫昏緫銆?*/
graph->arcnum++;
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
graph->edges[i][j] = weight;
/* 绗?{number}琛岋細杩涜鏉′欢鍒ゆ柇锛屽喅瀹氬綋鍓嶆祦绋嬭蛋鍝釜鍒嗘敮銆?*/
if (!graph->directed) {
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
graph->edges[j][i] = weight;
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細鎶婂綋鍓嶅嚱鏁扮殑缁撴灉杩斿洖缁欒皟鐢ㄨ€咃紝骞剁粨鏉熷綋鍓嶅嚱鏁般€?*/
return true;
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細杩欐槸鍘熸簮鐮侀噷宸茬粡瀛樺湪鐨勮鏄庢€ф敞閲娿€?*/
/* 打印邻接矩阵:便于把“图结构”和“矩阵内容”对应起来。 */
/* 绗?{number}琛岋細瀹氫箟鍑芥暟 ㈠紑濮嬪啓瀹冪殑鍏蜂綋瀹炵幇銆?*/
void PrintAMGraph(const AMGraph *graph) {
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
int i;
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
int j;
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細杩涜鏉′欢鍒ゆ柇锛屽喅瀹氬綋鍓嶆祦绋嬭蛋鍝釜鍒嗘敮銆?*/
if (graph == NULL) {
/* 绗?{number}琛岋細鎶婂綋鍓嶅嚱鏁扮殑缁撴灉杩斿洖缁欒皟鐢ㄨ€咃紝骞剁粨鏉熷綋鍓嶅嚱鏁般€?*/
return;
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細鎶婂綋鍓嶇粨鏋滄墦鍗板嚭鏉ワ紝鏂逛究瑙傚療绋嬪簭杩愯鎯呭喌銆?*/
printf("Adjacency Matrix:\n ");
/* 绗?{number}琛岋細寮€濮嬩竴娆?for 寰幆锛屾寜鍥哄畾娆℃暟閲嶅鎵ц鍚庨潰鐨勮鍙ャ€?*/
for (i = 0; i < graph->vexnum; i++) {
/* 绗?{number}琛岋細鎶婂綋鍓嶇粨鏋滄墦鍗板嚭鏉ワ紝鏂逛究瑙傚療绋嬪簭杩愯鎯呭喌銆?*/
printf(" %c", graph->vexs[i]);
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細鎶婂綋鍓嶇粨鏋滄墦鍗板嚭鏉ワ紝鏂逛究瑙傚療绋嬪簭杩愯鎯呭喌銆?*/
printf("\n");
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細寮€濮嬩竴娆?for 寰幆锛屾寜鍥哄畾娆℃暟閲嶅鎵ц鍚庨潰鐨勮鍙ャ€?*/
for (i = 0; i < graph->vexnum; i++) {
/* 绗?{number}琛岋細鎶婂綋鍓嶇粨鏋滄墦鍗板嚭鏉ワ紝鏂逛究瑙傚療绋嬪簭杩愯鎯呭喌銆?*/
printf(" %c ", graph->vexs[i]);
/* 绗?{number}琛岋細寮€濮嬩竴娆?for 寰幆锛屾寜鍥哄畾娆℃暟閲嶅鎵ц鍚庨潰鐨勮鍙ャ€?*/
for (j = 0; j < graph->vexnum; j++) {
/* 绗?{number}琛岋細杩涜鏉′欢鍒ゆ柇锛屽喅瀹氬綋鍓嶆祦绋嬭蛋鍝釜鍒嗘敮銆?*/
if (graph->edges[i][j] == INF) {
/* 绗?{number}琛岋細鎶婂綋鍓嶇粨鏋滄墦鍗板嚭鏉ワ紝鏂逛究瑙傚療绋嬪簭杩愯鎯呭喌銆?*/
printf(" -");
/* 绗?{number}琛岋細鎵ц杩欎竴琛屼唬鐮侊紝缁х画鎺ㄨ繘褰撳墠閫昏緫銆?*/
} else {
/* 绗?{number}琛岋細鎶婂綋鍓嶇粨鏋滄墦鍗板嚭鏉ワ紝鏂逛究瑙傚療绋嬪簭杩愯鎯呭喌銆?*/
printf(" %2d", graph->edges[i][j]);
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細鎶婂綋鍓嶇粨鏋滄墦鍗板嚭鏉ワ紝鏂逛究瑙傚療绋嬪簭杩愯鎯呭喌銆?*/
printf("\n");
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細杩欐槸鍘熸簮鐮侀噷宸茬粡瀛樺湪鐨勮鏄庢€ф敞閲娿€?*/
/* 创建邻接表边结点:把邻接点和权值封装起来。 */
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
ArcNode *CreateArcNode(int adjvex, int weight) {
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
ArcNode *node;
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
node = (ArcNode *)malloc(sizeof(ArcNode));
/* 绗?{number}琛岋細杩涜鏉′欢鍒ゆ柇锛屽喅瀹氬綋鍓嶆祦绋嬭蛋鍝釜鍒嗘敮銆?*/
if (node == NULL) {
/* 绗?{number}琛岋細鎶婂綋鍓嶅嚱鏁扮殑缁撴灉杩斿洖缁欒皟鐢ㄨ€咃紝骞剁粨鏉熷綋鍓嶅嚱鏁般€?*/
return NULL;
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
node->adjvex = adjvex;
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
node->weight = weight;
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
node->nextarc = NULL;
/* 绗?{number}琛岋細鎶婂綋鍓嶅嚱鏁扮殑缁撴灉杩斿洖缁欒皟鐢ㄨ€咃紝骞剁粨鏉熷綋鍓嶅嚱鏁般€?*/
return node;
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細杩欐槸鍘熸簮鐮侀噷宸茬粡瀛樺湪鐨勮鏄庢€ф敞閲娿€?*/
/* 初始化邻接表:先写顶点,再把每个顶点的第一条边指针置空。 */
/* 绗?{number}琛岋細瀹氫箟鍑芥暟 ㈠紑濮嬪啓瀹冪殑鍏蜂綋瀹炵幇銆?*/
void InitALGraph(ALGraph *graph, const char *vertex_names, bool directed) {
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
int i;
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
int length;
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細杩涜鏉′欢鍒ゆ柇锛屽喅瀹氬綋鍓嶆祦绋嬭蛋鍝釜鍒嗘敮銆?*/
if (graph == NULL || vertex_names == NULL) {
/* 绗?{number}琛岋細鎶婂綋鍓嶅嚱鏁扮殑缁撴灉杩斿洖缁欒皟鐢ㄨ€咃紝骞剁粨鏉熷綋鍓嶅嚱鏁般€?*/
return;
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
length = (int)strlen(vertex_names);
/* 绗?{number}琛岋細杩涜鏉′欢鍒ゆ柇锛屽喅瀹氬綋鍓嶆祦绋嬭蛋鍝釜鍒嗘敮銆?*/
if (length <= 0 || length > MAX_VERTEX_NUM) {
/* 绗?{number}琛岋細鎶婂綋鍓嶅嚱鏁扮殑缁撴灉杩斿洖缁欒皟鐢ㄨ€咃紝骞剁粨鏉熷綋鍓嶅嚱鏁般€?*/
return;
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
graph->vexnum = length;
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
graph->arcnum = 0;
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
graph->directed = directed;
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細寮€濮嬩竴娆?for 寰幆锛屾寜鍥哄畾娆℃暟閲嶅鎵ц鍚庨潰鐨勮鍙ャ€?*/
for (i = 0; i < graph->vexnum; i++) {
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
graph->vertices[i].data = vertex_names[i];
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
graph->vertices[i].firstarc = NULL;
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細杩欐槸鍘熸簮鐮侀噷宸茬粡瀛樺湪鐨勮鏄庢€ф敞閲娿€?*/
/* 按顶点名定位邻接表下标:和邻接矩阵版本保持相同思路。 */
/* 绗?{number}琛岋細瀹氫箟鍑芥暟 ㈠紑濮嬪啓瀹冪殑鍏蜂綋瀹炵幇銆?*/
int LocateVertexAL(const ALGraph *graph, char vertex) {
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
int i;
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細杩涜鏉′欢鍒ゆ柇锛屽喅瀹氬綋鍓嶆祦绋嬭蛋鍝釜鍒嗘敮銆?*/
if (graph == NULL) {
/* 绗?{number}琛岋細鎶婂綋鍓嶅嚱鏁扮殑缁撴灉杩斿洖缁欒皟鐢ㄨ€咃紝骞剁粨鏉熷綋鍓嶅嚱鏁般€?*/
return -1;
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細寮€濮嬩竴娆?for 寰幆锛屾寜鍥哄畾娆℃暟閲嶅鎵ц鍚庨潰鐨勮鍙ャ€?*/
for (i = 0; i < graph->vexnum; i++) {
/* 绗?{number}琛岋細杩涜鏉′欢鍒ゆ柇锛屽喅瀹氬綋鍓嶆祦绋嬭蛋鍝釜鍒嗘敮銆?*/
if (graph->vertices[i].data == vertex) {
/* 绗?{number}琛岋細鎶婂綋鍓嶅嚱鏁扮殑缁撴灉杩斿洖缁欒皟鐢ㄨ€咃紝骞剁粨鏉熷綋鍓嶅嚱鏁般€?*/
return i;
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細鎶婂綋鍓嶅嚱鏁扮殑缁撴灉杩斿洖缁欒皟鐢ㄨ€咃紝骞剁粨鏉熷綋鍓嶅嚱鏁般€?*/
return -1;
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細杩欐槸鍘熸簮鐮侀噷宸茬粡瀛樺湪鐨勮鏄庢€ф敞閲娿€?*/
/* 头插法挂一条边:新边结点插到邻接表最前面。 */
/* 绗?{number}琛岋細瀹氫箟鍑芥暟 ㈠紑濮嬪啓瀹冪殑鍏蜂綋瀹炵幇銆?*/
bool AddArcNode(ALGraph *graph, int from, int to, int weight) {
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
ArcNode *node;
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細杩涜鏉′欢鍒ゆ柇锛屽喅瀹氬綋鍓嶆祦绋嬭蛋鍝釜鍒嗘敮銆?*/
if (graph == NULL || from < 0 || from >= graph->vexnum || to < 0 || to >= graph->vexnum) {
/* 绗?{number}琛岋細鎶婂綋鍓嶅嚱鏁扮殑缁撴灉杩斿洖缁欒皟鐢ㄨ€咃紝骞剁粨鏉熷綋鍓嶅嚱鏁般€?*/
return false;
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
node = CreateArcNode(to, weight);
/* 绗?{number}琛岋細杩涜鏉′欢鍒ゆ柇锛屽喅瀹氬綋鍓嶆祦绋嬭蛋鍝釜鍒嗘敮銆?*/
if (node == NULL) {
/* 绗?{number}琛岋細鎶婂綋鍓嶅嚱鏁扮殑缁撴灉杩斿洖缁欒皟鐢ㄨ€咃紝骞剁粨鏉熷綋鍓嶅嚱鏁般€?*/
return false;
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
node->nextarc = graph->vertices[from].firstarc;
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
graph->vertices[from].firstarc = node;
/* 绗?{number}琛岋細鎶婂綋鍓嶅嚱鏁扮殑缁撴灉杩斿洖缁欒皟鐢ㄨ€咃紝骞剁粨鏉熷綋鍓嶅嚱鏁般€?*/
return true;
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細杩欐槸鍘熸簮鐮侀噷宸茬粡瀛樺湪鐨勮鏄庢€ф敞閲娿€?*/
/* 邻接表加边:无向图要补两次,有向图只补一次。 */
/* 绗?{number}琛岋細瀹氫箟鍑芥暟 ㈠紑濮嬪啓瀹冪殑鍏蜂綋瀹炵幇銆?*/
bool AddEdgeAL(ALGraph *graph, char from, char to, int weight) {
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
int i;
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
int j;
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細杩涜鏉′欢鍒ゆ柇锛屽喅瀹氬綋鍓嶆祦绋嬭蛋鍝釜鍒嗘敮銆?*/
if (graph == NULL || weight <= 0) {
/* 绗?{number}琛岋細鎶婂綋鍓嶅嚱鏁扮殑缁撴灉杩斿洖缁欒皟鐢ㄨ€咃紝骞剁粨鏉熷綋鍓嶅嚱鏁般€?*/
return false;
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
i = LocateVertexAL(graph, from);
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
j = LocateVertexAL(graph, to);
/* 绗?{number}琛岋細杩涜鏉′欢鍒ゆ柇锛屽喅瀹氬綋鍓嶆祦绋嬭蛋鍝釜鍒嗘敮銆?*/
if (i < 0 || j < 0 || i == j) {
/* 绗?{number}琛岋細鎶婂綋鍓嶅嚱鏁扮殑缁撴灉杩斿洖缁欒皟鐢ㄨ€咃紝骞剁粨鏉熷綋鍓嶅嚱鏁般€?*/
return false;
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細杩涜鏉′欢鍒ゆ柇锛屽喅瀹氬綋鍓嶆祦绋嬭蛋鍝釜鍒嗘敮銆?*/
if (!AddArcNode(graph, i, j, weight)) {
/* 绗?{number}琛岋細鎶婂綋鍓嶅嚱鏁扮殑缁撴灉杩斿洖缁欒皟鐢ㄨ€咃紝骞剁粨鏉熷綋鍓嶅嚱鏁般€?*/
return false;
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細杩涜鏉′欢鍒ゆ柇锛屽喅瀹氬綋鍓嶆祦绋嬭蛋鍝釜鍒嗘敮銆?*/
if (!graph->directed) {
/* 绗?{number}琛岋細杩涜鏉′欢鍒ゆ柇锛屽喅瀹氬綋鍓嶆祦绋嬭蛋鍝釜鍒嗘敮銆?*/
if (!AddArcNode(graph, j, i, weight)) {
/* 绗?{number}琛岋細鎶婂綋鍓嶅嚱鏁扮殑缁撴灉杩斿洖缁欒皟鐢ㄨ€咃紝骞剁粨鏉熷綋鍓嶅嚱鏁般€?*/
return false;
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細鎵ц杩欎竴琛屼唬鐮侊紝缁х画鎺ㄨ繘褰撳墠閫昏緫銆?*/
graph->arcnum++;
/* 绗?{number}琛岋細鎶婂綋鍓嶅嚱鏁扮殑缁撴灉杩斿洖缁欒皟鐢ㄨ€咃紝骞剁粨鏉熷綋鍓嶅嚱鏁般€?*/
return true;
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細杩欐槸鍘熸簮鐮侀噷宸茬粡瀛樺湪鐨勮鏄庢€ф敞閲娿€?*/
/* 打印邻接表:观察每个顶点后面都连了哪些邻接点。 */
/* 绗?{number}琛岋細瀹氫箟鍑芥暟 ㈠紑濮嬪啓瀹冪殑鍏蜂綋瀹炵幇銆?*/
void PrintALGraph(const ALGraph *graph) {
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
int i;
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
ArcNode *arc;
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細杩涜鏉′欢鍒ゆ柇锛屽喅瀹氬綋鍓嶆祦绋嬭蛋鍝釜鍒嗘敮銆?*/
if (graph == NULL) {
/* 绗?{number}琛岋細鎶婂綋鍓嶅嚱鏁扮殑缁撴灉杩斿洖缁欒皟鐢ㄨ€咃紝骞剁粨鏉熷綋鍓嶅嚱鏁般€?*/
return;
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細鎶婂綋鍓嶇粨鏋滄墦鍗板嚭鏉ワ紝鏂逛究瑙傚療绋嬪簭杩愯鎯呭喌銆?*/
printf("Adjacency List:\n");
/* 绗?{number}琛岋細寮€濮嬩竴娆?for 寰幆锛屾寜鍥哄畾娆℃暟閲嶅鎵ц鍚庨潰鐨勮鍙ャ€?*/
for (i = 0; i < graph->vexnum; i++) {
/* 绗?{number}琛岋細鎶婂綋鍓嶇粨鏋滄墦鍗板嚭鏉ワ紝鏂逛究瑙傚療绋嬪簭杩愯鎯呭喌銆?*/
printf("%c -> ", graph->vertices[i].data);
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
arc = graph->vertices[i].firstarc;
/* 绗?{number}琛岋細寮€濮嬩竴娆?while 寰幆锛屽彧瑕佹潯浠舵垚绔嬪氨缁х画鎵ц銆?*/
while (arc != NULL) {
/* 绗?{number}琛岋細鎶婂綋鍓嶇粨鏋滄墦鍗板嚭鏉ワ紝鏂逛究瑙傚療绋嬪簭杩愯鎯呭喌銆?*/
printf("(%c, w=%d) ", graph->vertices[arc->adjvex].data, arc->weight);
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
arc = arc->nextarc;
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細鎶婂綋鍓嶇粨鏋滄墦鍗板嚭鏉ワ紝鏂逛究瑙傚療绋嬪簭杩愯鎯呭喌銆?*/
printf("^\n");
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細杩欐槸鍘熸簮鐮侀噷宸茬粡瀛樺湪鐨勮鏄庢€ф敞閲娿€?*/
/* 释放邻接表:逐个顶点把边链表清掉,避免内存泄漏。 */
/* 绗?{number}琛岋細瀹氫箟鍑芥暟 ㈠紑濮嬪啓瀹冪殑鍏蜂綋瀹炵幇銆?*/
void DestroyALGraph(ALGraph *graph) {
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
int i;
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
ArcNode *current;
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
ArcNode *next;
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細杩涜鏉′欢鍒ゆ柇锛屽喅瀹氬綋鍓嶆祦绋嬭蛋鍝釜鍒嗘敮銆?*/
if (graph == NULL) {
/* 绗?{number}琛岋細鎶婂綋鍓嶅嚱鏁扮殑缁撴灉杩斿洖缁欒皟鐢ㄨ€咃紝骞剁粨鏉熷綋鍓嶅嚱鏁般€?*/
return;
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細寮€濮嬩竴娆?for 寰幆锛屾寜鍥哄畾娆℃暟閲嶅鎵ц鍚庨潰鐨勮鍙ャ€?*/
for (i = 0; i < graph->vexnum; i++) {
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
current = graph->vertices[i].firstarc;
/* 绗?{number}琛岋細寮€濮嬩竴娆?while 寰幆锛屽彧瑕佹潯浠舵垚绔嬪氨缁х画鎵ц銆?*/
while (current != NULL) {
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
next = current->nextarc;
/* 绗?{number}琛岋細璋冪敤涓€涓嚱鏁帮紝鍊熷姪瀹冨畬鎴愬綋鍓嶈繖涓€姝ユ搷浣溿€?*/
free(current);
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
current = next;
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
graph->vertices[i].firstarc = NULL;
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細杩欐槸鍘熸簮鐮侀噷宸茬粡瀛樺湪鐨勮鏄庢€ф敞閲娿€?*/
/* 访问顶点:统一输出接口,后续遍历都复用它。 */
/* 绗?{number}琛岋細瀹氫箟鍑芥暟 ㈠紑濮嬪啓瀹冪殑鍏蜂綋瀹炵幇銆?*/
void VisitVertex(char vertex) {
/* 绗?{number}琛岋細鎶婂綋鍓嶇粨鏋滄墦鍗板嚭鏉ワ紝鏂逛究瑙傚療绋嬪簭杩愯鎯呭喌銆?*/
printf("%c ", vertex);
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細杩欐槸鍘熸簮鐮侀噷宸茬粡瀛樺湪鐨勮鏄庢€ф敞閲娿€?*/
/* 邻接矩阵版 DFS 递归函数:先访问当前顶点,再递归访问尚未访问的邻接点。 */
/* 绗?{number}琛岋細瀹氫箟鍑芥暟 ㈠紑濮嬪啓瀹冪殑鍏蜂綋瀹炵幇銆?*/
void DFSAMUtil(const AMGraph *graph, int v, bool visited[]) {
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
int w;
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
visited[v] = true;
/* 绗?{number}琛岋細璋冪敤涓€涓嚱鏁帮紝鍊熷姪瀹冨畬鎴愬綋鍓嶈繖涓€姝ユ搷浣溿€?*/
VisitVertex(graph->vexs[v]);
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細寮€濮嬩竴娆?for 寰幆锛屾寜鍥哄畾娆℃暟閲嶅鎵ц鍚庨潰鐨勮鍙ャ€?*/
for (w = 0; w < graph->vexnum; w++) {
/* 绗?{number}琛岋細杩涜鏉′欢鍒ゆ柇锛屽喅瀹氬綋鍓嶆祦绋嬭蛋鍝釜鍒嗘敮銆?*/
if (!visited[w] && graph->edges[v][w] != INF && graph->edges[v][w] != 0) {
/* 绗?{number}琛岋細璋冪敤涓€涓嚱鏁帮紝鍊熷姪瀹冨畬鎴愬綋鍓嶈繖涓€姝ユ搷浣溿€?*/
DFSAMUtil(graph, w, visited);
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細杩欐槸鍘熸簮鐮侀噷宸茬粡瀛樺湪鐨勮鏄庢€ф敞閲娿€?*/
/* 邻接矩阵版 DFS:兼顾非连通图,必要时从新的连通分量重新出发。 */
/* 绗?{number}琛岋細瀹氫箟鍑芥暟 ㈠紑濮嬪啓瀹冪殑鍏蜂綋瀹炵幇銆?*/
void DFSAM(const AMGraph *graph) {
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
bool visited[MAX_VERTEX_NUM] = {false};
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
int i;
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細杩涜鏉′欢鍒ゆ柇锛屽喅瀹氬綋鍓嶆祦绋嬭蛋鍝釜鍒嗘敮銆?*/
if (graph == NULL) {
/* 绗?{number}琛岋細鎶婂綋鍓嶅嚱鏁扮殑缁撴灉杩斿洖缁欒皟鐢ㄨ€咃紝骞剁粨鏉熷綋鍓嶅嚱鏁般€?*/
return;
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細寮€濮嬩竴娆?for 寰幆锛屾寜鍥哄畾娆℃暟閲嶅鎵ц鍚庨潰鐨勮鍙ャ€?*/
for (i = 0; i < graph->vexnum; i++) {
/* 绗?{number}琛岋細杩涜鏉′欢鍒ゆ柇锛屽喅瀹氬綋鍓嶆祦绋嬭蛋鍝釜鍒嗘敮銆?*/
if (!visited[i]) {
/* 绗?{number}琛岋細璋冪敤涓€涓嚱鏁帮紝鍊熷姪瀹冨畬鎴愬綋鍓嶈繖涓€姝ユ搷浣溿€?*/
DFSAMUtil(graph, i, visited);
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細杩欐槸鍘熸簮鐮侀噷宸茬粡瀛樺湪鐨勮鏄庢€ф敞閲娿€?*/
/* 邻接矩阵版 BFS:先访问一个顶点,再按队列顺序逐层扩展。 */
/* 绗?{number}琛岋細瀹氫箟鍑芥暟 ㈠紑濮嬪啓瀹冪殑鍏蜂綋瀹炵幇銆?*/
void BFSAM(const AMGraph *graph) {
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
bool visited[MAX_VERTEX_NUM] = {false};
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
SqQueue queue;
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
int i;
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
int v;
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
int w;
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細杩涜鏉′欢鍒ゆ柇锛屽喅瀹氬綋鍓嶆祦绋嬭蛋鍝釜鍒嗘敮銆?*/
if (graph == NULL) {
/* 绗?{number}琛岋細鎶婂綋鍓嶅嚱鏁扮殑缁撴灉杩斿洖缁欒皟鐢ㄨ€咃紝骞剁粨鏉熷綋鍓嶅嚱鏁般€?*/
return;
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細璋冪敤涓€涓嚱鏁帮紝鍊熷姪瀹冨畬鎴愬綋鍓嶈繖涓€姝ユ搷浣溿€?*/
InitQueue(&queue);
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細寮€濮嬩竴娆?for 寰幆锛屾寜鍥哄畾娆℃暟閲嶅鎵ц鍚庨潰鐨勮鍙ャ€?*/
for (i = 0; i < graph->vexnum; i++) {
/* 绗?{number}琛岋細杩涜鏉′欢鍒ゆ柇锛屽喅瀹氬綋鍓嶆祦绋嬭蛋鍝釜鍒嗘敮銆?*/
if (visited[i]) {
/* 绗?{number}琛岋細鎵ц杩欎竴琛屼唬鐮侊紝缁х画鎺ㄨ繘褰撳墠閫昏緫銆?*/
continue;
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
visited[i] = true;
/* 绗?{number}琛岋細璋冪敤涓€涓嚱鏁帮紝鍊熷姪瀹冨畬鎴愬綋鍓嶈繖涓€姝ユ搷浣溿€?*/
VisitVertex(graph->vexs[i]);
/* 绗?{number}琛岋細璋冪敤涓€涓嚱鏁帮紝鍊熷姪瀹冨畬鎴愬綋鍓嶈繖涓€姝ユ搷浣溿€?*/
Enqueue(&queue, i);
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細寮€濮嬩竴娆?while 寰幆锛屽彧瑕佹潯浠舵垚绔嬪氨缁х画鎵ц銆?*/
while (!IsQueueEmpty(&queue)) {
/* 绗?{number}琛岋細璋冪敤涓€涓嚱鏁帮紝鍊熷姪瀹冨畬鎴愬綋鍓嶈繖涓€姝ユ搷浣溿€?*/
Dequeue(&queue, &v);
/* 绗?{number}琛岋細寮€濮嬩竴娆?for 寰幆锛屾寜鍥哄畾娆℃暟閲嶅鎵ц鍚庨潰鐨勮鍙ャ€?*/
for (w = 0; w < graph->vexnum; w++) {
/* 绗?{number}琛岋細杩涜鏉′欢鍒ゆ柇锛屽喅瀹氬綋鍓嶆祦绋嬭蛋鍝釜鍒嗘敮銆?*/
if (!visited[w] && graph->edges[v][w] != INF && graph->edges[v][w] != 0) {
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
visited[w] = true;
/* 绗?{number}琛岋細璋冪敤涓€涓嚱鏁帮紝鍊熷姪瀹冨畬鎴愬綋鍓嶈繖涓€姝ユ搷浣溿€?*/
VisitVertex(graph->vexs[w]);
/* 绗?{number}琛岋細璋冪敤涓€涓嚱鏁帮紝鍊熷姪瀹冨畬鎴愬綋鍓嶈繖涓€姝ユ搷浣溿€?*/
Enqueue(&queue, w);
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細杩欐槸鍘熸簮鐮侀噷宸茬粡瀛樺湪鐨勮鏄庢€ф敞閲娿€?*/
/* 邻接表版 DFS 递归函数:顺着边链表把当前顶点能到的点一路走深。 */
/* 绗?{number}琛岋細瀹氫箟鍑芥暟 ㈠紑濮嬪啓瀹冪殑鍏蜂綋瀹炵幇銆?*/
void DFSALUtil(const ALGraph *graph, int v, bool visited[]) {
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
ArcNode *arc;
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
visited[v] = true;
/* 绗?{number}琛岋細璋冪敤涓€涓嚱鏁帮紝鍊熷姪瀹冨畬鎴愬綋鍓嶈繖涓€姝ユ搷浣溿€?*/
VisitVertex(graph->vertices[v].data);
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
arc = graph->vertices[v].firstarc;
/* 绗?{number}琛岋細寮€濮嬩竴娆?while 寰幆锛屽彧瑕佹潯浠舵垚绔嬪氨缁х画鎵ц銆?*/
while (arc != NULL) {
/* 绗?{number}琛岋細杩涜鏉′欢鍒ゆ柇锛屽喅瀹氬綋鍓嶆祦绋嬭蛋鍝釜鍒嗘敮銆?*/
if (!visited[arc->adjvex]) {
/* 绗?{number}琛岋細璋冪敤涓€涓嚱鏁帮紝鍊熷姪瀹冨畬鎴愬綋鍓嶈繖涓€姝ユ搷浣溿€?*/
DFSALUtil(graph, arc->adjvex, visited);
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
arc = arc->nextarc;
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細杩欐槸鍘熸簮鐮侀噷宸茬粡瀛樺湪鐨勮鏄庢€ф敞閲娿€?*/
/* 邻接表版 DFS:写法和矩阵版类似,只是邻接点获取方式不同。 */
/* 绗?{number}琛岋細瀹氫箟鍑芥暟 ㈠紑濮嬪啓瀹冪殑鍏蜂綋瀹炵幇銆?*/
void DFSAL(const ALGraph *graph) {
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
bool visited[MAX_VERTEX_NUM] = {false};
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
int i;
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細杩涜鏉′欢鍒ゆ柇锛屽喅瀹氬綋鍓嶆祦绋嬭蛋鍝釜鍒嗘敮銆?*/
if (graph == NULL) {
/* 绗?{number}琛岋細鎶婂綋鍓嶅嚱鏁扮殑缁撴灉杩斿洖缁欒皟鐢ㄨ€咃紝骞剁粨鏉熷綋鍓嶅嚱鏁般€?*/
return;
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細寮€濮嬩竴娆?for 寰幆锛屾寜鍥哄畾娆℃暟閲嶅鎵ц鍚庨潰鐨勮鍙ャ€?*/
for (i = 0; i < graph->vexnum; i++) {
/* 绗?{number}琛岋細杩涜鏉′欢鍒ゆ柇锛屽喅瀹氬綋鍓嶆祦绋嬭蛋鍝釜鍒嗘敮銆?*/
if (!visited[i]) {
/* 绗?{number}琛岋細璋冪敤涓€涓嚱鏁帮紝鍊熷姪瀹冨畬鎴愬綋鍓嶈繖涓€姝ユ搷浣溿€?*/
DFSALUtil(graph, i, visited);
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細杩欐槸鍘熸簮鐮侀噷宸茬粡瀛樺湪鐨勮鏄庢€ф敞閲娿€?*/
/* 邻接表版 BFS:队列逻辑不变,只是遍历邻接点时改成扫边链表。 */
/* 绗?{number}琛岋細瀹氫箟鍑芥暟 ㈠紑濮嬪啓瀹冪殑鍏蜂綋瀹炵幇銆?*/
void BFSAL(const ALGraph *graph) {
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
bool visited[MAX_VERTEX_NUM] = {false};
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
SqQueue queue;
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
ArcNode *arc;
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
int i;
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
int v;
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細杩涜鏉′欢鍒ゆ柇锛屽喅瀹氬綋鍓嶆祦绋嬭蛋鍝釜鍒嗘敮銆?*/
if (graph == NULL) {
/* 绗?{number}琛岋細鎶婂綋鍓嶅嚱鏁扮殑缁撴灉杩斿洖缁欒皟鐢ㄨ€咃紝骞剁粨鏉熷綋鍓嶅嚱鏁般€?*/
return;
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細璋冪敤涓€涓嚱鏁帮紝鍊熷姪瀹冨畬鎴愬綋鍓嶈繖涓€姝ユ搷浣溿€?*/
InitQueue(&queue);
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細寮€濮嬩竴娆?for 寰幆锛屾寜鍥哄畾娆℃暟閲嶅鎵ц鍚庨潰鐨勮鍙ャ€?*/
for (i = 0; i < graph->vexnum; i++) {
/* 绗?{number}琛岋細杩涜鏉′欢鍒ゆ柇锛屽喅瀹氬綋鍓嶆祦绋嬭蛋鍝釜鍒嗘敮銆?*/
if (visited[i]) {
/* 绗?{number}琛岋細鎵ц杩欎竴琛屼唬鐮侊紝缁х画鎺ㄨ繘褰撳墠閫昏緫銆?*/
continue;
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
visited[i] = true;
/* 绗?{number}琛岋細璋冪敤涓€涓嚱鏁帮紝鍊熷姪瀹冨畬鎴愬綋鍓嶈繖涓€姝ユ搷浣溿€?*/
VisitVertex(graph->vertices[i].data);
/* 绗?{number}琛岋細璋冪敤涓€涓嚱鏁帮紝鍊熷姪瀹冨畬鎴愬綋鍓嶈繖涓€姝ユ搷浣溿€?*/
Enqueue(&queue, i);
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細寮€濮嬩竴娆?while 寰幆锛屽彧瑕佹潯浠舵垚绔嬪氨缁х画鎵ц銆?*/
while (!IsQueueEmpty(&queue)) {
/* 绗?{number}琛岋細璋冪敤涓€涓嚱鏁帮紝鍊熷姪瀹冨畬鎴愬綋鍓嶈繖涓€姝ユ搷浣溿€?*/
Dequeue(&queue, &v);
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
arc = graph->vertices[v].firstarc;
/* 绗?{number}琛岋細寮€濮嬩竴娆?while 寰幆锛屽彧瑕佹潯浠舵垚绔嬪氨缁х画鎵ц銆?*/
while (arc != NULL) {
/* 绗?{number}琛岋細杩涜鏉′欢鍒ゆ柇锛屽喅瀹氬綋鍓嶆祦绋嬭蛋鍝釜鍒嗘敮銆?*/
if (!visited[arc->adjvex]) {
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
visited[arc->adjvex] = true;
/* 绗?{number}琛岋細璋冪敤涓€涓嚱鏁帮紝鍊熷姪瀹冨畬鎴愬綋鍓嶈繖涓€姝ユ搷浣溿€?*/
VisitVertex(graph->vertices[arc->adjvex].data);
/* 绗?{number}琛岋細璋冪敤涓€涓嚱鏁帮紝鍊熷姪瀹冨畬鎴愬綋鍓嶈繖涓€姝ユ搷浣溿€?*/
Enqueue(&queue, arc->adjvex);
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
arc = arc->nextarc;
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細杩欐槸鍘熸簮鐮侀噷宸茬粡瀛樺湪鐨勮鏄庢€ф敞閲娿€?*/
/* 只做标记不输出的 DFS:后面统计连通分量时更方便复用。 */
/* 绗?{number}琛岋細瀹氫箟鍑芥暟 ㈠紑濮嬪啓瀹冪殑鍏蜂綋瀹炵幇銆?*/
void DFSMarkAM(const AMGraph *graph, int v, bool visited[]) {
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
int w;
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
visited[v] = true;
/* 绗?{number}琛岋細寮€濮嬩竴娆?for 寰幆锛屾寜鍥哄畾娆℃暟閲嶅鎵ц鍚庨潰鐨勮鍙ャ€?*/
for (w = 0; w < graph->vexnum; w++) {
/* 绗?{number}琛岋細杩涜鏉′欢鍒ゆ柇锛屽喅瀹氬綋鍓嶆祦绋嬭蛋鍝釜鍒嗘敮銆?*/
if (!visited[w] && graph->edges[v][w] != INF && graph->edges[v][w] != 0) {
/* 绗?{number}琛岋細璋冪敤涓€涓嚱鏁帮紝鍊熷姪瀹冨畬鎴愬綋鍓嶈繖涓€姝ユ搷浣溿€?*/
DFSMarkAM(graph, w, visited);
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細杩欐槸鍘熸簮鐮侀噷宸茬粡瀛樺湪鐨勮鏄庢€ф敞閲娿€?*/
/* 统计无向图连通分量:每发现一个还没访问过的顶点,就说明找到一个新分量。 */
/* 绗?{number}琛岋細瀹氫箟鍑芥暟 ㈠紑濮嬪啓瀹冪殑鍏蜂綋瀹炵幇銆?*/
int CountConnectedComponentsAM(const AMGraph *graph) {
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
bool visited[MAX_VERTEX_NUM] = {false};
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
int components;
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
int i;
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細杩涜鏉′欢鍒ゆ柇锛屽喅瀹氬綋鍓嶆祦绋嬭蛋鍝釜鍒嗘敮銆?*/
if (graph == NULL) {
/* 绗?{number}琛岋細鎶婂綋鍓嶅嚱鏁扮殑缁撴灉杩斿洖缁欒皟鐢ㄨ€咃紝骞剁粨鏉熷綋鍓嶅嚱鏁般€?*/
return 0;
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
components = 0;
/* 绗?{number}琛岋細寮€濮嬩竴娆?for 寰幆锛屾寜鍥哄畾娆℃暟閲嶅鎵ц鍚庨潰鐨勮鍙ャ€?*/
for (i = 0; i < graph->vexnum; i++) {
/* 绗?{number}琛岋細杩涜鏉′欢鍒ゆ柇锛屽喅瀹氬綋鍓嶆祦绋嬭蛋鍝釜鍒嗘敮銆?*/
if (!visited[i]) {
/* 绗?{number}琛岋細鎵ц杩欎竴琛屼唬鐮侊紝缁х画鎺ㄨ繘褰撳墠閫昏緫銆?*/
components++;
/* 绗?{number}琛岋細璋冪敤涓€涓嚱鏁帮紝鍊熷姪瀹冨畬鎴愬綋鍓嶈繖涓€姝ユ搷浣溿€?*/
DFSMarkAM(graph, i, visited);
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細鎶婂綋鍓嶅嚱鏁扮殑缁撴灉杩斿洖缁欒皟鐢ㄨ€咃紝骞剁粨鏉熷綋鍓嶅嚱鏁般€?*/
return components;
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細杩欐槸鍘熸簮鐮侀噷宸茬粡瀛樺湪鐨勮鏄庢€ф敞閲娿€?*/
/* 拓扑排序:不断取入度为 0 的顶点输出,并删除其发出的边。 */
/* 绗?{number}琛岋細瀹氫箟鍑芥暟 ㈠紑濮嬪啓瀹冪殑鍏蜂綋瀹炵幇銆?*/
bool TopologicalSortAL(const ALGraph *graph, char order[]) {
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
int indegree[MAX_VERTEX_NUM] = {0};
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
SqQueue queue;
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
ArcNode *arc;
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
int i;
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
int v;
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
int count;
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細杩涜鏉′欢鍒ゆ柇锛屽喅瀹氬綋鍓嶆祦绋嬭蛋鍝釜鍒嗘敮銆?*/
if (graph == NULL || order == NULL) {
/* 绗?{number}琛岋細鎶婂綋鍓嶅嚱鏁扮殑缁撴灉杩斿洖缁欒皟鐢ㄨ€咃紝骞剁粨鏉熷綋鍓嶅嚱鏁般€?*/
return false;
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細寮€濮嬩竴娆?for 寰幆锛屾寜鍥哄畾娆℃暟閲嶅鎵ц鍚庨潰鐨勮鍙ャ€?*/
for (i = 0; i < graph->vexnum; i++) {
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
arc = graph->vertices[i].firstarc;
/* 绗?{number}琛岋細寮€濮嬩竴娆?while 寰幆锛屽彧瑕佹潯浠舵垚绔嬪氨缁х画鎵ц銆?*/
while (arc != NULL) {
/* 绗?{number}琛岋細鎵ц杩欎竴琛屼唬鐮侊紝缁х画鎺ㄨ繘褰撳墠閫昏緫銆?*/
indegree[arc->adjvex]++;
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
arc = arc->nextarc;
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細璋冪敤涓€涓嚱鏁帮紝鍊熷姪瀹冨畬鎴愬綋鍓嶈繖涓€姝ユ搷浣溿€?*/
InitQueue(&queue);
/* 绗?{number}琛岋細寮€濮嬩竴娆?for 寰幆锛屾寜鍥哄畾娆℃暟閲嶅鎵ц鍚庨潰鐨勮鍙ャ€?*/
for (i = 0; i < graph->vexnum; i++) {
/* 绗?{number}琛岋細杩涜鏉′欢鍒ゆ柇锛屽喅瀹氬綋鍓嶆祦绋嬭蛋鍝釜鍒嗘敮銆?*/
if (indegree[i] == 0) {
/* 绗?{number}琛岋細璋冪敤涓€涓嚱鏁帮紝鍊熷姪瀹冨畬鎴愬綋鍓嶈繖涓€姝ユ搷浣溿€?*/
Enqueue(&queue, i);
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
count = 0;
/* 绗?{number}琛岋細寮€濮嬩竴娆?while 寰幆锛屽彧瑕佹潯浠舵垚绔嬪氨缁х画鎵ц銆?*/
while (!IsQueueEmpty(&queue)) {
/* 绗?{number}琛岋細璋冪敤涓€涓嚱鏁帮紝鍊熷姪瀹冨畬鎴愬綋鍓嶈繖涓€姝ユ搷浣溿€?*/
Dequeue(&queue, &v);
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
order[count++] = graph->vertices[v].data;
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
arc = graph->vertices[v].firstarc;
/* 绗?{number}琛岋細寮€濮嬩竴娆?while 寰幆锛屽彧瑕佹潯浠舵垚绔嬪氨缁х画鎵ц銆?*/
while (arc != NULL) {
/* 绗?{number}琛岋細鎵ц杩欎竴琛屼唬鐮侊紝缁х画鎺ㄨ繘褰撳墠閫昏緫銆?*/
indegree[arc->adjvex]--;
/* 绗?{number}琛岋細杩涜鏉′欢鍒ゆ柇锛屽喅瀹氬綋鍓嶆祦绋嬭蛋鍝釜鍒嗘敮銆?*/
if (indegree[arc->adjvex] == 0) {
/* 绗?{number}琛岋細璋冪敤涓€涓嚱鏁帮紝鍊熷姪瀹冨畬鎴愬綋鍓嶈繖涓€姝ユ搷浣溿€?*/
Enqueue(&queue, arc->adjvex);
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
arc = arc->nextarc;
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
order[count] = '\0';
/* 绗?{number}琛岋細鎶婂綋鍓嶅嚱鏁扮殑缁撴灉杩斿洖缁欒皟鐢ㄨ€咃紝骞剁粨鏉熷綋鍓嶅嚱鏁般€?*/
return count == graph->vexnum;
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細杩欐槸鍘熸簮鐮侀噷宸茬粡瀛樺湪鐨勮鏄庢€ф敞閲娿€?*/
/* 求并查集根结点:一路向上找代表元,并顺手做路径压缩。 */
/* 绗?{number}琛岋細瀹氫箟鍑芥暟 ㈠紑濮嬪啓瀹冪殑鍏蜂綋瀹炵幇銆?*/
int FindSet(int parent[], int x) {
/* 绗?{number}琛岋細杩涜鏉′欢鍒ゆ柇锛屽喅瀹氬綋鍓嶆祦绋嬭蛋鍝釜鍒嗘敮銆?*/
if (parent[x] != x) {
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
parent[x] = FindSet(parent, parent[x]);
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細鎶婂綋鍓嶅嚱鏁扮殑缁撴灉杩斿洖缁欒皟鐢ㄨ€咃紝骞剁粨鏉熷綋鍓嶅嚱鏁般€?*/
return parent[x];
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細杩欐槸鍘熸簮鐮侀噷宸茬粡瀛樺湪鐨勮鏄庢€ф敞閲娿€?*/
/* 合并两个集合:把秩较小的树挂到秩较大的树下面,减少后续查找高度。 */
/* 绗?{number}琛岋細瀹氫箟鍑芥暟 ㈠紑濮嬪啓瀹冪殑鍏蜂綋瀹炵幇銆?*/
void UnionSet(int parent[], int rank[], int x, int y) {
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
int root_x;
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
int root_y;
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
root_x = FindSet(parent, x);
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
root_y = FindSet(parent, y);
/* 绗?{number}琛岋細杩涜鏉′欢鍒ゆ柇锛屽喅瀹氬綋鍓嶆祦绋嬭蛋鍝釜鍒嗘敮銆?*/
if (root_x == root_y) {
/* 绗?{number}琛岋細鎶婂綋鍓嶅嚱鏁扮殑缁撴灉杩斿洖缁欒皟鐢ㄨ€咃紝骞剁粨鏉熷綋鍓嶅嚱鏁般€?*/
return;
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細杩涜鏉′欢鍒ゆ柇锛屽喅瀹氬綋鍓嶆祦绋嬭蛋鍝釜鍒嗘敮銆?*/
if (rank[root_x] < rank[root_y]) {
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
parent[root_x] = root_y;
/* 绗?{number}琛岋細鎵ц杩欎竴琛屼唬鐮侊紝缁х画鎺ㄨ繘褰撳墠閫昏緫銆?*/
} else if (rank[root_x] > rank[root_y]) {
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
parent[root_y] = root_x;
/* 绗?{number}琛岋細鎵ц杩欎竴琛屼唬鐮侊紝缁х画鎺ㄨ繘褰撳墠閫昏緫銆?*/
} else {
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
parent[root_y] = root_x;
/* 绗?{number}琛岋細鎵ц杩欎竴琛屼唬鐮侊紝缁х画鎺ㄨ繘褰撳墠閫昏緫銆?*/
rank[root_x]++;
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細杩欐槸鍘熸簮鐮侀噷宸茬粡瀛樺湪鐨勮鏄庢€ф敞閲娿€?*/
/* 给 qsort 用的比较函数:边权更小的边排在前面,方便 Kruskal 逐条尝试。 */
/* 绗?{number}琛岋細瀹氫箟鍑芥暟 ㈠紑濮嬪啓瀹冪殑鍏蜂綋瀹炵幇銆?*/
int CompareEdgeByWeight(const void *lhs, const void *rhs) {
/* 绗?{number}琛岋細鎵ц杩欎竴琛屼唬鐮侊紝缁х画鎺ㄨ繘褰撳墠閫昏緫銆?*/
const Edge *left;
/* 绗?{number}琛岋細鎵ц杩欎竴琛屼唬鐮侊紝缁х画鎺ㄨ繘褰撳墠閫昏緫銆?*/
const Edge *right;
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
left = (const Edge *)lhs;
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
right = (const Edge *)rhs;
/* 绗?{number}琛岋細鎶婂綋鍓嶅嚱鏁扮殑缁撴灉杩斿洖缁欒皟鐢ㄨ€咃紝骞剁粨鏉熷綋鍓嶅嚱鏁般€?*/
return left->weight - right->weight;
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細杩欐槸鍘熸簮鐮侀噷宸茬粡瀛樺湪鐨勮鏄庢€ф敞閲娿€?*/
/* Kruskal 算法:把所有边按权值从小到大尝试,能接且不成环就选中。 */
/* 绗?{number}琛岋細瀹氫箟鍑芥暟 ㈠紑濮嬪啓瀹冪殑鍏蜂綋瀹炵幇銆?*/
int KruskalMSTWeightAM(const AMGraph *graph) {
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
Edge edges[MAX_VERTEX_NUM * MAX_VERTEX_NUM];
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
int parent[MAX_VERTEX_NUM];
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
int rank[MAX_VERTEX_NUM] = {0};
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
int edge_count;
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
int selected_edges;
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
int total_weight;
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
int i;
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
int j;
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細杩涜鏉′欢鍒ゆ柇锛屽喅瀹氬綋鍓嶆祦绋嬭蛋鍝釜鍒嗘敮銆?*/
if (graph == NULL || graph->directed || graph->vexnum == 0) {
/* 绗?{number}琛岋細鎶婂綋鍓嶅嚱鏁扮殑缁撴灉杩斿洖缁欒皟鐢ㄨ€咃紝骞剁粨鏉熷綋鍓嶅嚱鏁般€?*/
return -1;
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
edge_count = 0;
/* 绗?{number}琛岋細寮€濮嬩竴娆?for 寰幆锛屾寜鍥哄畾娆℃暟閲嶅鎵ц鍚庨潰鐨勮鍙ャ€?*/
for (i = 0; i < graph->vexnum; i++) {
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
parent[i] = i;
/* 绗?{number}琛岋細寮€濮嬩竴娆?for 寰幆锛屾寜鍥哄畾娆℃暟閲嶅鎵ц鍚庨潰鐨勮鍙ャ€?*/
for (j = i + 1; j < graph->vexnum; j++) {
/* 绗?{number}琛岋細杩涜鏉′欢鍒ゆ柇锛屽喅瀹氬綋鍓嶆祦绋嬭蛋鍝釜鍒嗘敮銆?*/
if (graph->edges[i][j] != INF && graph->edges[i][j] != 0) {
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
edges[edge_count].u = i;
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
edges[edge_count].v = j;
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
edges[edge_count].weight = graph->edges[i][j];
/* 绗?{number}琛岋細鎵ц杩欎竴琛屼唬鐮侊紝缁х画鎺ㄨ繘褰撳墠閫昏緫銆?*/
edge_count++;
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細璋冪敤涓€涓嚱鏁帮紝鍊熷姪瀹冨畬鎴愬綋鍓嶈繖涓€姝ユ搷浣溿€?*/
qsort(edges, edge_count, sizeof(Edge), CompareEdgeByWeight);
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
total_weight = 0;
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
selected_edges = 0;
/* 绗?{number}琛岋細寮€濮嬩竴娆?for 寰幆锛屾寜鍥哄畾娆℃暟閲嶅鎵ц鍚庨潰鐨勮鍙ャ€?*/
for (i = 0; i < edge_count && selected_edges < graph->vexnum - 1; i++) {
/* 绗?{number}琛岋細杩涜鏉′欢鍒ゆ柇锛屽喅瀹氬綋鍓嶆祦绋嬭蛋鍝釜鍒嗘敮銆?*/
if (FindSet(parent, edges[i].u) != FindSet(parent, edges[i].v)) {
/* 绗?{number}琛岋細璋冪敤涓€涓嚱鏁帮紝鍊熷姪瀹冨畬鎴愬綋鍓嶈繖涓€姝ユ搷浣溿€?*/
UnionSet(parent, rank, edges[i].u, edges[i].v);
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
total_weight += edges[i].weight;
/* 绗?{number}琛岋細鎵ц杩欎竴琛屼唬鐮侊紝缁х画鎺ㄨ繘褰撳墠閫昏緫銆?*/
selected_edges++;
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細杩涜鏉′欢鍒ゆ柇锛屽喅瀹氬綋鍓嶆祦绋嬭蛋鍝釜鍒嗘敮銆?*/
if (selected_edges != graph->vexnum - 1) {
/* 绗?{number}琛岋細鎶婂綋鍓嶅嚱鏁扮殑缁撴灉杩斿洖缁欒皟鐢ㄨ€咃紝骞剁粨鏉熷綋鍓嶅嚱鏁般€?*/
return -1;
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細鎶婂綋鍓嶅嚱鏁扮殑缁撴灉杩斿洖缁欒皟鐢ㄨ€咃紝骞剁粨鏉熷綋鍓嶅嚱鏁般€?*/
return total_weight;
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細杩欐槸鍘熸簮鐮侀噷宸茬粡瀛樺湪鐨勮鏄庢€ф敞閲娿€?*/
/* Prim 算法求最小生成树权值:每次把当前生成树到外部的最短边接进来。 */
/* 绗?{number}琛岋細瀹氫箟鍑芥暟 ㈠紑濮嬪啓瀹冪殑鍏蜂綋瀹炵幇銆?*/
int PrimMSTWeightAM(const AMGraph *graph, int start) {
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
int lowcost[MAX_VERTEX_NUM];
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
bool in_tree[MAX_VERTEX_NUM] = {false};
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
int i;
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
int j;
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
int min_cost;
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
int next_vertex;
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
int total_weight;
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細杩涜鏉′欢鍒ゆ柇锛屽喅瀹氬綋鍓嶆祦绋嬭蛋鍝釜鍒嗘敮銆?*/
if (graph == NULL || start < 0 || start >= graph->vexnum || graph->vexnum == 0) {
/* 绗?{number}琛岋細鎶婂綋鍓嶅嚱鏁扮殑缁撴灉杩斿洖缁欒皟鐢ㄨ€咃紝骞剁粨鏉熷綋鍓嶅嚱鏁般€?*/
return -1;
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細寮€濮嬩竴娆?for 寰幆锛屾寜鍥哄畾娆℃暟閲嶅鎵ц鍚庨潰鐨勮鍙ャ€?*/
for (i = 0; i < graph->vexnum; i++) {
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
lowcost[i] = graph->edges[start][i];
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
in_tree[start] = true;
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
total_weight = 0;
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細寮€濮嬩竴娆?for 寰幆锛屾寜鍥哄畾娆℃暟閲嶅鎵ц鍚庨潰鐨勮鍙ャ€?*/
for (i = 1; i < graph->vexnum; i++) {
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
min_cost = INF;
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
next_vertex = -1;
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細寮€濮嬩竴娆?for 寰幆锛屾寜鍥哄畾娆℃暟閲嶅鎵ц鍚庨潰鐨勮鍙ャ€?*/
for (j = 0; j < graph->vexnum; j++) {
/* 绗?{number}琛岋細杩涜鏉′欢鍒ゆ柇锛屽喅瀹氬綋鍓嶆祦绋嬭蛋鍝釜鍒嗘敮銆?*/
if (!in_tree[j] && lowcost[j] < min_cost) {
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
min_cost = lowcost[j];
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
next_vertex = j;
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細杩涜鏉′欢鍒ゆ柇锛屽喅瀹氬綋鍓嶆祦绋嬭蛋鍝釜鍒嗘敮銆?*/
if (next_vertex == -1) {
/* 绗?{number}琛岋細鎶婂綋鍓嶅嚱鏁扮殑缁撴灉杩斿洖缁欒皟鐢ㄨ€咃紝骞剁粨鏉熷綋鍓嶅嚱鏁般€?*/
return -1;
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
in_tree[next_vertex] = true;
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
total_weight += min_cost;
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細寮€濮嬩竴娆?for 寰幆锛屾寜鍥哄畾娆℃暟閲嶅鎵ц鍚庨潰鐨勮鍙ャ€?*/
for (j = 0; j < graph->vexnum; j++) {
/* 绗?{number}琛岋細杩涜鏉′欢鍒ゆ柇锛屽喅瀹氬綋鍓嶆祦绋嬭蛋鍝釜鍒嗘敮銆?*/
if (!in_tree[j] && graph->edges[next_vertex][j] < lowcost[j]) {
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
lowcost[j] = graph->edges[next_vertex][j];
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細鎶婂綋鍓嶅嚱鏁扮殑缁撴灉杩斿洖缁欒皟鐢ㄨ€咃紝骞剁粨鏉熷綋鍓嶅嚱鏁般€?*/
return total_weight;
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細杩欐槸鍘熸簮鐮侀噷宸茬粡瀛樺湪鐨勮鏄庢€ф敞閲娿€?*/
/* Floyd 算法:允许每个顶点依次作为中转点,不断改进任意两点间的最短路。 */
/* 绗?{number}琛岋細瀹氫箟鍑芥暟 ㈠紑濮嬪啓瀹冪殑鍏蜂綋瀹炵幇銆?*/
void FloydAM(const AMGraph *graph, int dist[][MAX_VERTEX_NUM], int path[][MAX_VERTEX_NUM]) {
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
int i;
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
int j;
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
int k;
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細杩涜鏉′欢鍒ゆ柇锛屽喅瀹氬綋鍓嶆祦绋嬭蛋鍝釜鍒嗘敮銆?*/
if (graph == NULL || dist == NULL || path == NULL) {
/* 绗?{number}琛岋細鎶婂綋鍓嶅嚱鏁扮殑缁撴灉杩斿洖缁欒皟鐢ㄨ€咃紝骞剁粨鏉熷綋鍓嶅嚱鏁般€?*/
return;
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細寮€濮嬩竴娆?for 寰幆锛屾寜鍥哄畾娆℃暟閲嶅鎵ц鍚庨潰鐨勮鍙ャ€?*/
for (i = 0; i < graph->vexnum; i++) {
/* 绗?{number}琛岋細寮€濮嬩竴娆?for 寰幆锛屾寜鍥哄畾娆℃暟閲嶅鎵ц鍚庨潰鐨勮鍙ャ€?*/
for (j = 0; j < graph->vexnum; j++) {
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
dist[i][j] = graph->edges[i][j];
/* 绗?{number}琛岋細杩涜鏉′欢鍒ゆ柇锛屽喅瀹氬綋鍓嶆祦绋嬭蛋鍝釜鍒嗘敮銆?*/
if (i != j && graph->edges[i][j] != INF) {
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
path[i][j] = j;
/* 绗?{number}琛岋細鎵ц杩欎竴琛屼唬鐮侊紝缁х画鎺ㄨ繘褰撳墠閫昏緫銆?*/
} else {
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
path[i][j] = -1;
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細寮€濮嬩竴娆?for 寰幆锛屾寜鍥哄畾娆℃暟閲嶅鎵ц鍚庨潰鐨勮鍙ャ€?*/
for (k = 0; k < graph->vexnum; k++) {
/* 绗?{number}琛岋細寮€濮嬩竴娆?for 寰幆锛屾寜鍥哄畾娆℃暟閲嶅鎵ц鍚庨潰鐨勮鍙ャ€?*/
for (i = 0; i < graph->vexnum; i++) {
/* 绗?{number}琛岋細寮€濮嬩竴娆?for 寰幆锛屾寜鍥哄畾娆℃暟閲嶅鎵ц鍚庨潰鐨勮鍙ャ€?*/
for (j = 0; j < graph->vexnum; j++) {
/* 绗?{number}琛岋細杩涜鏉′欢鍒ゆ柇锛屽喅瀹氬綋鍓嶆祦绋嬭蛋鍝釜鍒嗘敮銆?*/
if (dist[i][k] == INF || dist[k][j] == INF) {
/* 绗?{number}琛岋細鎵ц杩欎竴琛屼唬鐮侊紝缁х画鎺ㄨ繘褰撳墠閫昏緫銆?*/
continue;
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細杩涜鏉′欢鍒ゆ柇锛屽喅瀹氬綋鍓嶆祦绋嬭蛋鍝釜鍒嗘敮銆?*/
if (dist[i][k] + dist[k][j] < dist[i][j]) {
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
dist[i][j] = dist[i][k] + dist[k][j];
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
path[i][j] = path[i][k];
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細杩欐槸鍘熸簮鐮侀噷宸茬粡瀛樺湪鐨勮鏄庢€ф敞閲娿€?*/
/* 打印 Floyd 距离矩阵:便于一次性观察任意两点间的最短路径长度。 */
/* 绗?{number}琛岋細瀹氫箟鍑芥暟 ㈠紑濮嬪啓瀹冪殑鍏蜂綋瀹炵幇銆?*/
void PrintFloydDistances(const AMGraph *graph, int dist[][MAX_VERTEX_NUM]) {
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
int i;
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
int j;
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細杩涜鏉′欢鍒ゆ柇锛屽喅瀹氬綋鍓嶆祦绋嬭蛋鍝釜鍒嗘敮銆?*/
if (graph == NULL || dist == NULL) {
/* 绗?{number}琛岋細鎶婂綋鍓嶅嚱鏁扮殑缁撴灉杩斿洖缁欒皟鐢ㄨ€咃紝骞剁粨鏉熷綋鍓嶅嚱鏁般€?*/
return;
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細鎶婂綋鍓嶇粨鏋滄墦鍗板嚭鏉ワ紝鏂逛究瑙傚療绋嬪簭杩愯鎯呭喌銆?*/
printf("Floyd distance matrix:\n ");
/* 绗?{number}琛岋細寮€濮嬩竴娆?for 寰幆锛屾寜鍥哄畾娆℃暟閲嶅鎵ц鍚庨潰鐨勮鍙ャ€?*/
for (i = 0; i < graph->vexnum; i++) {
/* 绗?{number}琛岋細鎶婂綋鍓嶇粨鏋滄墦鍗板嚭鏉ワ紝鏂逛究瑙傚療绋嬪簭杩愯鎯呭喌銆?*/
printf(" %c", graph->vexs[i]);
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細鎶婂綋鍓嶇粨鏋滄墦鍗板嚭鏉ワ紝鏂逛究瑙傚療绋嬪簭杩愯鎯呭喌銆?*/
printf("\n");
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細寮€濮嬩竴娆?for 寰幆锛屾寜鍥哄畾娆℃暟閲嶅鎵ц鍚庨潰鐨勮鍙ャ€?*/
for (i = 0; i < graph->vexnum; i++) {
/* 绗?{number}琛岋細鎶婂綋鍓嶇粨鏋滄墦鍗板嚭鏉ワ紝鏂逛究瑙傚療绋嬪簭杩愯鎯呭喌銆?*/
printf(" %c ", graph->vexs[i]);
/* 绗?{number}琛岋細寮€濮嬩竴娆?for 寰幆锛屾寜鍥哄畾娆℃暟閲嶅鎵ц鍚庨潰鐨勮鍙ャ€?*/
for (j = 0; j < graph->vexnum; j++) {
/* 绗?{number}琛岋細杩涜鏉′欢鍒ゆ柇锛屽喅瀹氬綋鍓嶆祦绋嬭蛋鍝釜鍒嗘敮銆?*/
if (dist[i][j] == INF) {
/* 绗?{number}琛岋細鎶婂綋鍓嶇粨鏋滄墦鍗板嚭鏉ワ紝鏂逛究瑙傚療绋嬪簭杩愯鎯呭喌銆?*/
printf(" -");
/* 绗?{number}琛岋細鎵ц杩欎竴琛屼唬鐮侊紝缁х画鎺ㄨ繘褰撳墠閫昏緫銆?*/
} else {
/* 绗?{number}琛岋細鎶婂綋鍓嶇粨鏋滄墦鍗板嚭鏉ワ紝鏂逛究瑙傚療绋嬪簭杩愯鎯呭喌銆?*/
printf(" %2d", dist[i][j]);
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細鎶婂綋鍓嶇粨鏋滄墦鍗板嚭鏉ワ紝鏂逛究瑙傚療绋嬪簭杩愯鎯呭喌銆?*/
printf("\n");
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細杩欐槸鍘熸簮鐮侀噷宸茬粡瀛樺湪鐨勮鏄庢€ф敞閲娿€?*/
/* 打印 Floyd 还原出的具体路径:沿着 path 数组记录的“下一跳”一路走到终点。 */
/* 绗?{number}琛岋細瀹氫箟鍑芥暟 ㈠紑濮嬪啓瀹冪殑鍏蜂綋瀹炵幇銆?*/
void PrintFloydPathAM(const AMGraph *graph, int path[][MAX_VERTEX_NUM], int from, int to) {
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
int current;
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細杩涜鏉′欢鍒ゆ柇锛屽喅瀹氬綋鍓嶆祦绋嬭蛋鍝釜鍒嗘敮銆?*/
if (graph == NULL || path == NULL || from < 0 || to < 0 ||
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
from >= graph->vexnum || to >= graph->vexnum) {
/* 绗?{number}琛岋細鎶婂綋鍓嶅嚱鏁扮殑缁撴灉杩斿洖缁欒皟鐢ㄨ€咃紝骞剁粨鏉熷綋鍓嶅嚱鏁般€?*/
return;
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細杩涜鏉′欢鍒ゆ柇锛屽喅瀹氬綋鍓嶆祦绋嬭蛋鍝釜鍒嗘敮銆?*/
if (from == to) {
/* 绗?{number}琛岋細鎶婂綋鍓嶇粨鏋滄墦鍗板嚭鏉ワ紝鏂逛究瑙傚療绋嬪簭杩愯鎯呭喌銆?*/
printf("%c\n", graph->vexs[from]);
/* 绗?{number}琛岋細鎶婂綋鍓嶅嚱鏁扮殑缁撴灉杩斿洖缁欒皟鐢ㄨ€咃紝骞剁粨鏉熷綋鍓嶅嚱鏁般€?*/
return;
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細杩涜鏉′欢鍒ゆ柇锛屽喅瀹氬綋鍓嶆祦绋嬭蛋鍝釜鍒嗘敮銆?*/
if (path[from][to] == -1) {
/* 绗?{number}琛岋細鎶婂綋鍓嶇粨鏋滄墦鍗板嚭鏉ワ紝鏂逛究瑙傚療绋嬪簭杩愯鎯呭喌銆?*/
printf("No path\n");
/* 绗?{number}琛岋細鎶婂綋鍓嶅嚱鏁扮殑缁撴灉杩斿洖缁欒皟鐢ㄨ€咃紝骞剁粨鏉熷綋鍓嶅嚱鏁般€?*/
return;
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
current = from;
/* 绗?{number}琛岋細鎶婂綋鍓嶇粨鏋滄墦鍗板嚭鏉ワ紝鏂逛究瑙傚療绋嬪簭杩愯鎯呭喌銆?*/
printf("%c", graph->vexs[current]);
/* 绗?{number}琛岋細寮€濮嬩竴娆?while 寰幆锛屽彧瑕佹潯浠舵垚绔嬪氨缁х画鎵ц銆?*/
while (current != to) {
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
current = path[current][to];
/* 绗?{number}琛岋細杩涜鏉′欢鍒ゆ柇锛屽喅瀹氬綋鍓嶆祦绋嬭蛋鍝釜鍒嗘敮銆?*/
if (current == -1) {
/* 绗?{number}琛岋細鎶婂綋鍓嶇粨鏋滄墦鍗板嚭鏉ワ紝鏂逛究瑙傚療绋嬪簭杩愯鎯呭喌銆?*/
printf(" -> ?\n");
/* 绗?{number}琛岋細鎶婂綋鍓嶅嚱鏁扮殑缁撴灉杩斿洖缁欒皟鐢ㄨ€咃紝骞剁粨鏉熷綋鍓嶅嚱鏁般€?*/
return;
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細鎶婂綋鍓嶇粨鏋滄墦鍗板嚭鏉ワ紝鏂逛究瑙傚療绋嬪簭杩愯鎯呭喌銆?*/
printf(" -> %c", graph->vexs[current]);
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細鎶婂綋鍓嶇粨鏋滄墦鍗板嚭鏉ワ紝鏂逛究瑙傚療绋嬪簭杩愯鎯呭喌銆?*/
printf("\n");
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細杩欐槸鍘熸簮鐮侀噷宸茬粡瀛樺湪鐨勮鏄庢€ф敞閲娿€?*/
/* Dijkstra 单源最短路径:dist 记录当前最短估计,finalized 记录顶点是否已确定最短路。 */
/* 绗?{number}琛岋細瀹氫箟鍑芥暟 ㈠紑濮嬪啓瀹冪殑鍏蜂綋瀹炵幇銆?*/
void DijkstraAM(const AMGraph *graph, int source, int dist[], int path[]) {
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
bool finalized[MAX_VERTEX_NUM] = {false};
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
int i;
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
int j;
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
int min_dist;
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
int u;
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細杩涜鏉′欢鍒ゆ柇锛屽喅瀹氬綋鍓嶆祦绋嬭蛋鍝釜鍒嗘敮銆?*/
if (graph == NULL || dist == NULL || path == NULL || source < 0 || source >= graph->vexnum) {
/* 绗?{number}琛岋細鎶婂綋鍓嶅嚱鏁扮殑缁撴灉杩斿洖缁欒皟鐢ㄨ€咃紝骞剁粨鏉熷綋鍓嶅嚱鏁般€?*/
return;
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細寮€濮嬩竴娆?for 寰幆锛屾寜鍥哄畾娆℃暟閲嶅鎵ц鍚庨潰鐨勮鍙ャ€?*/
for (i = 0; i < graph->vexnum; i++) {
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
dist[i] = graph->edges[source][i];
/* 绗?{number}琛岋細杩涜鏉′欢鍒ゆ柇锛屽喅瀹氬綋鍓嶆祦绋嬭蛋鍝釜鍒嗘敮銆?*/
if (i != source && graph->edges[source][i] != INF) {
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
path[i] = source;
/* 绗?{number}琛岋細鎵ц杩欎竴琛屼唬鐮侊紝缁х画鎺ㄨ繘褰撳墠閫昏緫銆?*/
} else {
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
path[i] = -1;
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
dist[source] = 0;
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
finalized[source] = true;
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細寮€濮嬩竴娆?for 寰幆锛屾寜鍥哄畾娆℃暟閲嶅鎵ц鍚庨潰鐨勮鍙ャ€?*/
for (i = 1; i < graph->vexnum; i++) {
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
min_dist = INF;
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
u = -1;
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細寮€濮嬩竴娆?for 寰幆锛屾寜鍥哄畾娆℃暟閲嶅鎵ц鍚庨潰鐨勮鍙ャ€?*/
for (j = 0; j < graph->vexnum; j++) {
/* 绗?{number}琛岋細杩涜鏉′欢鍒ゆ柇锛屽喅瀹氬綋鍓嶆祦绋嬭蛋鍝釜鍒嗘敮銆?*/
if (!finalized[j] && dist[j] < min_dist) {
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
min_dist = dist[j];
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
u = j;
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細杩涜鏉′欢鍒ゆ柇锛屽喅瀹氬綋鍓嶆祦绋嬭蛋鍝釜鍒嗘敮銆?*/
if (u == -1) {
/* 绗?{number}琛岋細鎵ц杩欎竴琛屼唬鐮侊紝缁х画鎺ㄨ繘褰撳墠閫昏緫銆?*/
break;
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
finalized[u] = true;
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細寮€濮嬩竴娆?for 寰幆锛屾寜鍥哄畾娆℃暟閲嶅鎵ц鍚庨潰鐨勮鍙ャ€?*/
for (j = 0; j < graph->vexnum; j++) {
/* 绗?{number}琛岋細杩涜鏉′欢鍒ゆ柇锛屽喅瀹氬綋鍓嶆祦绋嬭蛋鍝釜鍒嗘敮銆?*/
if (!finalized[j] &&
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
graph->edges[u][j] != INF &&
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
dist[u] != INF &&
/* 绗?{number}琛岋細鎵ц杩欎竴琛屼唬鐮侊紝缁х画鎺ㄨ繘褰撳墠閫昏緫銆?*/
dist[u] + graph->edges[u][j] < dist[j]) {
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
dist[j] = dist[u] + graph->edges[u][j];
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
path[j] = u;
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細杩欐槸鍘熸簮鐮侀噷宸茬粡瀛樺湪鐨勮鏄庢€ф敞閲娿€?*/
/* 打印 Dijkstra 结果:便于把每个顶点的最短路长度直接看出来。 */
/* 绗?{number}琛岋細瀹氫箟鍑芥暟 ㈠紑濮嬪啓瀹冪殑鍏蜂綋瀹炵幇銆?*/
void PrintDijkstraResult(const AMGraph *graph, int source, const int dist[]) {
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
int i;
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細杩涜鏉′欢鍒ゆ柇锛屽喅瀹氬綋鍓嶆祦绋嬭蛋鍝釜鍒嗘敮銆?*/
if (graph == NULL || dist == NULL) {
/* 绗?{number}琛岋細鎶婂綋鍓嶅嚱鏁扮殑缁撴灉杩斿洖缁欒皟鐢ㄨ€咃紝骞剁粨鏉熷綋鍓嶅嚱鏁般€?*/
return;
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細鎶婂綋鍓嶇粨鏋滄墦鍗板嚭鏉ワ紝鏂逛究瑙傚療绋嬪簭杩愯鎯呭喌銆?*/
printf("Dijkstra distances from %c: ", graph->vexs[source]);
/* 绗?{number}琛岋細寮€濮嬩竴娆?for 寰幆锛屾寜鍥哄畾娆℃暟閲嶅鎵ц鍚庨潰鐨勮鍙ャ€?*/
for (i = 0; i < graph->vexnum; i++) {
/* 绗?{number}琛岋細杩涜鏉′欢鍒ゆ柇锛屽喅瀹氬綋鍓嶆祦绋嬭蛋鍝釜鍒嗘敮銆?*/
if (dist[i] == INF) {
/* 绗?{number}琛岋細鎶婂綋鍓嶇粨鏋滄墦鍗板嚭鏉ワ紝鏂逛究瑙傚療绋嬪簭杩愯鎯呭喌銆?*/
printf("%c=INF ", graph->vexs[i]);
/* 绗?{number}琛岋細鎵ц杩欎竴琛屼唬鐮侊紝缁х画鎺ㄨ繘褰撳墠閫昏緫銆?*/
} else {
/* 绗?{number}琛岋細鎶婂綋鍓嶇粨鏋滄墦鍗板嚭鏉ワ紝鏂逛究瑙傚療绋嬪簭杩愯鎯呭喌銆?*/
printf("%c=%d ", graph->vexs[i], dist[i]);
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細鎶婂綋鍓嶇粨鏋滄墦鍗板嚭鏉ワ紝鏂逛究瑙傚療绋嬪簭杩愯鎯呭喌銆?*/
printf("\n");
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細杩欐槸鍘熸簮鐮侀噷宸茬粡瀛樺湪鐨勮鏄庢€ф敞閲娿€?*/
/* 生成拓扑序下标:关键路径既要正推最早时间,也要逆推最迟时间,所以先保留顺序。 */
/* 绗?{number}琛岋細瀹氫箟鍑芥暟 ㈠紑濮嬪啓瀹冪殑鍏蜂綋瀹炵幇銆?*/
bool GetTopologicalOrderAL(const ALGraph *graph, int order[], int *count) {
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
int indegree[MAX_VERTEX_NUM] = {0};
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
SqQueue queue;
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
ArcNode *arc;
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
int i;
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
int v;
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
int total;
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細杩涜鏉′欢鍒ゆ柇锛屽喅瀹氬綋鍓嶆祦绋嬭蛋鍝釜鍒嗘敮銆?*/
if (graph == NULL || order == NULL || count == NULL) {
/* 绗?{number}琛岋細鎶婂綋鍓嶅嚱鏁扮殑缁撴灉杩斿洖缁欒皟鐢ㄨ€咃紝骞剁粨鏉熷綋鍓嶅嚱鏁般€?*/
return false;
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細寮€濮嬩竴娆?for 寰幆锛屾寜鍥哄畾娆℃暟閲嶅鎵ц鍚庨潰鐨勮鍙ャ€?*/
for (i = 0; i < graph->vexnum; i++) {
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
arc = graph->vertices[i].firstarc;
/* 绗?{number}琛岋細寮€濮嬩竴娆?while 寰幆锛屽彧瑕佹潯浠舵垚绔嬪氨缁х画鎵ц銆?*/
while (arc != NULL) {
/* 绗?{number}琛岋細鎵ц杩欎竴琛屼唬鐮侊紝缁х画鎺ㄨ繘褰撳墠閫昏緫銆?*/
indegree[arc->adjvex]++;
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
arc = arc->nextarc;
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細璋冪敤涓€涓嚱鏁帮紝鍊熷姪瀹冨畬鎴愬綋鍓嶈繖涓€姝ユ搷浣溿€?*/
InitQueue(&queue);
/* 绗?{number}琛岋細寮€濮嬩竴娆?for 寰幆锛屾寜鍥哄畾娆℃暟閲嶅鎵ц鍚庨潰鐨勮鍙ャ€?*/
for (i = 0; i < graph->vexnum; i++) {
/* 绗?{number}琛岋細杩涜鏉′欢鍒ゆ柇锛屽喅瀹氬綋鍓嶆祦绋嬭蛋鍝釜鍒嗘敮銆?*/
if (indegree[i] == 0) {
/* 绗?{number}琛岋細璋冪敤涓€涓嚱鏁帮紝鍊熷姪瀹冨畬鎴愬綋鍓嶈繖涓€姝ユ搷浣溿€?*/
Enqueue(&queue, i);
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
total = 0;
/* 绗?{number}琛岋細寮€濮嬩竴娆?while 寰幆锛屽彧瑕佹潯浠舵垚绔嬪氨缁х画鎵ц銆?*/
while (!IsQueueEmpty(&queue)) {
/* 绗?{number}琛岋細璋冪敤涓€涓嚱鏁帮紝鍊熷姪瀹冨畬鎴愬綋鍓嶈繖涓€姝ユ搷浣溿€?*/
Dequeue(&queue, &v);
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
order[total++] = v;
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
arc = graph->vertices[v].firstarc;
/* 绗?{number}琛岋細寮€濮嬩竴娆?while 寰幆锛屽彧瑕佹潯浠舵垚绔嬪氨缁х画鎵ц銆?*/
while (arc != NULL) {
/* 绗?{number}琛岋細鎵ц杩欎竴琛屼唬鐮侊紝缁х画鎺ㄨ繘褰撳墠閫昏緫銆?*/
indegree[arc->adjvex]--;
/* 绗?{number}琛岋細杩涜鏉′欢鍒ゆ柇锛屽喅瀹氬綋鍓嶆祦绋嬭蛋鍝釜鍒嗘敮銆?*/
if (indegree[arc->adjvex] == 0) {
/* 绗?{number}琛岋細璋冪敤涓€涓嚱鏁帮紝鍊熷姪瀹冨畬鎴愬綋鍓嶈繖涓€姝ユ搷浣溿€?*/
Enqueue(&queue, arc->adjvex);
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
arc = arc->nextarc;
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
*count = total;
/* 绗?{number}琛岋細鎶婂綋鍓嶅嚱鏁扮殑缁撴灉杩斿洖缁欒皟鐢ㄨ€咃紝骞剁粨鏉熷綋鍓嶅嚱鏁般€?*/
return total == graph->vexnum;
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細杩欐槸鍘熸簮鐮侀噷宸茬粡瀛樺湪鐨勮鏄庢€ф敞閲娿€?*/
/* 关键路径:先正推事件最早发生时间,再逆推最迟发生时间,最后找时差为 0 的活动。 */
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
bool CriticalPathAL(const ALGraph *graph,
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
int ve[],
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
int vl[],
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
bool critical[][MAX_VERTEX_NUM],
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
int *critical_length) {
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
int order[MAX_VERTEX_NUM];
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
int count;
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
ArcNode *arc;
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
int i;
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
int v;
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
int ee;
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
int el;
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
int project_length;
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細杩涜鏉′欢鍒ゆ柇锛屽喅瀹氬綋鍓嶆祦绋嬭蛋鍝釜鍒嗘敮銆?*/
if (graph == NULL || ve == NULL || vl == NULL || critical == NULL || critical_length == NULL) {
/* 绗?{number}琛岋細鎶婂綋鍓嶅嚱鏁扮殑缁撴灉杩斿洖缁欒皟鐢ㄨ€咃紝骞剁粨鏉熷綋鍓嶅嚱鏁般€?*/
return false;
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細杩涜鏉′欢鍒ゆ柇锛屽喅瀹氬綋鍓嶆祦绋嬭蛋鍝釜鍒嗘敮銆?*/
if (!GetTopologicalOrderAL(graph, order, &count)) {
/* 绗?{number}琛岋細鎶婂綋鍓嶅嚱鏁扮殑缁撴灉杩斿洖缁欒皟鐢ㄨ€咃紝骞剁粨鏉熷綋鍓嶅嚱鏁般€?*/
return false;
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細寮€濮嬩竴娆?for 寰幆锛屾寜鍥哄畾娆℃暟閲嶅鎵ц鍚庨潰鐨勮鍙ャ€?*/
for (i = 0; i < graph->vexnum; i++) {
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
ve[i] = 0;
/* 绗?{number}琛岋細寮€濮嬩竴娆?for 寰幆锛屾寜鍥哄畾娆℃暟閲嶅鎵ц鍚庨潰鐨勮鍙ャ€?*/
for (v = 0; v < graph->vexnum; v++) {
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
critical[i][v] = false;
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細寮€濮嬩竴娆?for 寰幆锛屾寜鍥哄畾娆℃暟閲嶅鎵ц鍚庨潰鐨勮鍙ャ€?*/
for (i = 0; i < count; i++) {
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
v = order[i];
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
arc = graph->vertices[v].firstarc;
/* 绗?{number}琛岋細寮€濮嬩竴娆?while 寰幆锛屽彧瑕佹潯浠舵垚绔嬪氨缁х画鎵ц銆?*/
while (arc != NULL) {
/* 绗?{number}琛岋細杩涜鏉′欢鍒ゆ柇锛屽喅瀹氬綋鍓嶆祦绋嬭蛋鍝釜鍒嗘敮銆?*/
if (ve[v] + arc->weight > ve[arc->adjvex]) {
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
ve[arc->adjvex] = ve[v] + arc->weight;
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
arc = arc->nextarc;
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
project_length = 0;
/* 绗?{number}琛岋細寮€濮嬩竴娆?for 寰幆锛屾寜鍥哄畾娆℃暟閲嶅鎵ц鍚庨潰鐨勮鍙ャ€?*/
for (i = 0; i < graph->vexnum; i++) {
/* 绗?{number}琛岋細杩涜鏉′欢鍒ゆ柇锛屽喅瀹氬綋鍓嶆祦绋嬭蛋鍝釜鍒嗘敮銆?*/
if (ve[i] > project_length) {
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
project_length = ve[i];
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
vl[i] = project_length;
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細寮€濮嬩竴娆?for 寰幆锛屾寜鍥哄畾娆℃暟閲嶅鎵ц鍚庨潰鐨勮鍙ャ€?*/
for (i = count - 1; i >= 0; i--) {
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
v = order[i];
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
arc = graph->vertices[v].firstarc;
/* 绗?{number}琛岋細寮€濮嬩竴娆?while 寰幆锛屽彧瑕佹潯浠舵垚绔嬪氨缁х画鎵ц銆?*/
while (arc != NULL) {
/* 绗?{number}琛岋細杩涜鏉′欢鍒ゆ柇锛屽喅瀹氬綋鍓嶆祦绋嬭蛋鍝釜鍒嗘敮銆?*/
if (vl[arc->adjvex] - arc->weight < vl[v]) {
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
vl[v] = vl[arc->adjvex] - arc->weight;
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
arc = arc->nextarc;
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細寮€濮嬩竴娆?for 寰幆锛屾寜鍥哄畾娆℃暟閲嶅鎵ц鍚庨潰鐨勮鍙ャ€?*/
for (v = 0; v < graph->vexnum; v++) {
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
arc = graph->vertices[v].firstarc;
/* 绗?{number}琛岋細寮€濮嬩竴娆?while 寰幆锛屽彧瑕佹潯浠舵垚绔嬪氨缁х画鎵ц銆?*/
while (arc != NULL) {
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
ee = ve[v];
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
el = vl[arc->adjvex] - arc->weight;
/* 绗?{number}琛岋細杩涜鏉′欢鍒ゆ柇锛屽喅瀹氬綋鍓嶆祦绋嬭蛋鍝釜鍒嗘敮銆?*/
if (ee == el) {
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
critical[v][arc->adjvex] = true;
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
arc = arc->nextarc;
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
*critical_length = project_length;
/* 绗?{number}琛岋細鎶婂綋鍓嶅嚱鏁扮殑缁撴灉杩斿洖缁欒皟鐢ㄨ€咃紝骞剁粨鏉熷綋鍓嶅嚱鏁般€?*/
return true;
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細杩欐槸鍘熸簮鐮侀噷宸茬粡瀛樺湪鐨勮鏄庢€ф敞閲娿€?*/
/* 打印关键路径结果:先输出 ve/vl,再列出关键活动,方便把表和图对应起来。 */
/* 绗?{number}琛岋細鎵ц杩欎竴琛屼唬鐮侊紝缁х画鎺ㄨ繘褰撳墠閫昏緫銆?*/
void PrintCriticalPathResult(const ALGraph *graph,
/* 绗?{number}琛岋細鎵ц杩欎竴琛屼唬鐮侊紝缁х画鎺ㄨ繘褰撳墠閫昏緫銆?*/
const int ve[],
/* 绗?{number}琛岋細鎵ц杩欎竴琛屼唬鐮侊紝缁х画鎺ㄨ繘褰撳墠閫昏緫銆?*/
const int vl[],
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
bool critical[][MAX_VERTEX_NUM],
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
int critical_length) {
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
ArcNode *arc;
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
int i;
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細杩涜鏉′欢鍒ゆ柇锛屽喅瀹氬綋鍓嶆祦绋嬭蛋鍝釜鍒嗘敮銆?*/
if (graph == NULL || ve == NULL || vl == NULL || critical == NULL) {
/* 绗?{number}琛岋細鎶婂綋鍓嶅嚱鏁扮殑缁撴灉杩斿洖缁欒皟鐢ㄨ€咃紝骞剁粨鏉熷綋鍓嶅嚱鏁般€?*/
return;
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細鎶婂綋鍓嶇粨鏋滄墦鍗板嚭鏉ワ紝鏂逛究瑙傚療绋嬪簭杩愯鎯呭喌銆?*/
printf("Critical path project length: %d\n", critical_length);
/* 绗?{number}琛岋細鎶婂綋鍓嶇粨鏋滄墦鍗板嚭鏉ワ紝鏂逛究瑙傚療绋嬪簭杩愯鎯呭喌銆?*/
printf("ve: ");
/* 绗?{number}琛岋細寮€濮嬩竴娆?for 寰幆锛屾寜鍥哄畾娆℃暟閲嶅鎵ц鍚庨潰鐨勮鍙ャ€?*/
for (i = 0; i < graph->vexnum; i++) {
/* 绗?{number}琛岋細鎶婂綋鍓嶇粨鏋滄墦鍗板嚭鏉ワ紝鏂逛究瑙傚療绋嬪簭杩愯鎯呭喌銆?*/
printf("%c=%d ", graph->vertices[i].data, ve[i]);
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細鎶婂綋鍓嶇粨鏋滄墦鍗板嚭鏉ワ紝鏂逛究瑙傚療绋嬪簭杩愯鎯呭喌銆?*/
printf("\n");
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細鎶婂綋鍓嶇粨鏋滄墦鍗板嚭鏉ワ紝鏂逛究瑙傚療绋嬪簭杩愯鎯呭喌銆?*/
printf("vl: ");
/* 绗?{number}琛岋細寮€濮嬩竴娆?for 寰幆锛屾寜鍥哄畾娆℃暟閲嶅鎵ц鍚庨潰鐨勮鍙ャ€?*/
for (i = 0; i < graph->vexnum; i++) {
/* 绗?{number}琛岋細鎶婂綋鍓嶇粨鏋滄墦鍗板嚭鏉ワ紝鏂逛究瑙傚療绋嬪簭杩愯鎯呭喌銆?*/
printf("%c=%d ", graph->vertices[i].data, vl[i]);
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細鎶婂綋鍓嶇粨鏋滄墦鍗板嚭鏉ワ紝鏂逛究瑙傚療绋嬪簭杩愯鎯呭喌銆?*/
printf("\n");
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細鎶婂綋鍓嶇粨鏋滄墦鍗板嚭鏉ワ紝鏂逛究瑙傚療绋嬪簭杩愯鎯呭喌銆?*/
printf("Critical activities: ");
/* 绗?{number}琛岋細寮€濮嬩竴娆?for 寰幆锛屾寜鍥哄畾娆℃暟閲嶅鎵ц鍚庨潰鐨勮鍙ャ€?*/
for (i = 0; i < graph->vexnum; i++) {
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
arc = graph->vertices[i].firstarc;
/* 绗?{number}琛岋細寮€濮嬩竴娆?while 寰幆锛屽彧瑕佹潯浠舵垚绔嬪氨缁х画鎵ц銆?*/
while (arc != NULL) {
/* 绗?{number}琛岋細杩涜鏉′欢鍒ゆ柇锛屽喅瀹氬綋鍓嶆祦绋嬭蛋鍝釜鍒嗘敮銆?*/
if (critical[i][arc->adjvex]) {
/* 绗?{number}琛岋細鎶婂綋鍓嶇粨鏋滄墦鍗板嚭鏉ワ紝鏂逛究瑙傚療绋嬪簭杩愯鎯呭喌銆?*/
printf("<%c,%c> ", graph->vertices[i].data, graph->vertices[arc->adjvex].data);
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細缁欏彉閲忋€佹暟缁勩€佸瓧娈垫垨鎸囬拡璧嬪€硷紝鏇存柊褰撳墠鐘舵€併€?*/
arc = arc->nextarc;
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細鎶婂綋鍓嶇粨鏋滄墦鍗板嚭鏉ワ紝鏂逛究瑙傚療绋嬪簭杩愯鎯呭喌銆?*/
printf("\n");
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細杩欐槸鍘熸簮鐮侀噷宸茬粡瀛樺湪鐨勮鏄庢€ф敞閲娿€?*/
/* 构造一张示例无向图:后面统一用它演示矩阵、邻接表、DFS、BFS。 */
/* 绗?{number}琛岋細瀹氫箟鍑芥暟 ㈠紑濮嬪啓瀹冪殑鍏蜂綋瀹炵幇銆?*/
void BuildSampleGraphs(AMGraph *matrix_graph, ALGraph *list_graph) {
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
const char *vertices = "ABCDE";
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細璋冪敤涓€涓嚱鏁帮紝鍊熷姪瀹冨畬鎴愬綋鍓嶈繖涓€姝ユ搷浣溿€?*/
InitAMGraph(matrix_graph, vertices, false);
/* 绗?{number}琛岋細璋冪敤涓€涓嚱鏁帮紝鍊熷姪瀹冨畬鎴愬綋鍓嶈繖涓€姝ユ搷浣溿€?*/
InitALGraph(list_graph, vertices, false);
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細璋冪敤涓€涓嚱鏁帮紝鍊熷姪瀹冨畬鎴愬綋鍓嶈繖涓€姝ユ搷浣溿€?*/
AddEdgeAM(matrix_graph, 'A', 'B', 1);
/* 绗?{number}琛岋細璋冪敤涓€涓嚱鏁帮紝鍊熷姪瀹冨畬鎴愬綋鍓嶈繖涓€姝ユ搷浣溿€?*/
AddEdgeAM(matrix_graph, 'A', 'C', 1);
/* 绗?{number}琛岋細璋冪敤涓€涓嚱鏁帮紝鍊熷姪瀹冨畬鎴愬綋鍓嶈繖涓€姝ユ搷浣溿€?*/
AddEdgeAM(matrix_graph, 'B', 'D', 1);
/* 绗?{number}琛岋細璋冪敤涓€涓嚱鏁帮紝鍊熷姪瀹冨畬鎴愬綋鍓嶈繖涓€姝ユ搷浣溿€?*/
AddEdgeAM(matrix_graph, 'C', 'D', 1);
/* 绗?{number}琛岋細璋冪敤涓€涓嚱鏁帮紝鍊熷姪瀹冨畬鎴愬綋鍓嶈繖涓€姝ユ搷浣溿€?*/
AddEdgeAM(matrix_graph, 'C', 'E', 1);
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細璋冪敤涓€涓嚱鏁帮紝鍊熷姪瀹冨畬鎴愬綋鍓嶈繖涓€姝ユ搷浣溿€?*/
AddEdgeAL(list_graph, 'A', 'B', 1);
/* 绗?{number}琛岋細璋冪敤涓€涓嚱鏁帮紝鍊熷姪瀹冨畬鎴愬綋鍓嶈繖涓€姝ユ搷浣溿€?*/
AddEdgeAL(list_graph, 'A', 'C', 1);
/* 绗?{number}琛岋細璋冪敤涓€涓嚱鏁帮紝鍊熷姪瀹冨畬鎴愬綋鍓嶈繖涓€姝ユ搷浣溿€?*/
AddEdgeAL(list_graph, 'B', 'D', 1);
/* 绗?{number}琛岋細璋冪敤涓€涓嚱鏁帮紝鍊熷姪瀹冨畬鎴愬綋鍓嶈繖涓€姝ユ搷浣溿€?*/
AddEdgeAL(list_graph, 'C', 'D', 1);
/* 绗?{number}琛岋細璋冪敤涓€涓嚱鏁帮紝鍊熷姪瀹冨畬鎴愬綋鍓嶈繖涓€姝ユ搷浣溿€?*/
AddEdgeAL(list_graph, 'C', 'E', 1);
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細杩欐槸鍘熸簮鐮侀噷宸茬粡瀛樺湪鐨勮鏄庢€ф敞閲娿€?*/
/* 构造示例 DAG:后面用它演示拓扑排序。 */
/* 绗?{number}琛岋細瀹氫箟鍑芥暟 ㈠紑濮嬪啓瀹冪殑鍏蜂綋瀹炵幇銆?*/
void BuildSampleDAG(ALGraph *dag) {
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
const char *vertices = "ABCDEF";
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細璋冪敤涓€涓嚱鏁帮紝鍊熷姪瀹冨畬鎴愬綋鍓嶈繖涓€姝ユ搷浣溿€?*/
InitALGraph(dag, vertices, true);
/* 绗?{number}琛岋細璋冪敤涓€涓嚱鏁帮紝鍊熷姪瀹冨畬鎴愬綋鍓嶈繖涓€姝ユ搷浣溿€?*/
AddEdgeAL(dag, 'A', 'C', 1);
/* 绗?{number}琛岋細璋冪敤涓€涓嚱鏁帮紝鍊熷姪瀹冨畬鎴愬綋鍓嶈繖涓€姝ユ搷浣溿€?*/
AddEdgeAL(dag, 'A', 'D', 1);
/* 绗?{number}琛岋細璋冪敤涓€涓嚱鏁帮紝鍊熷姪瀹冨畬鎴愬綋鍓嶈繖涓€姝ユ搷浣溿€?*/
AddEdgeAL(dag, 'B', 'D', 1);
/* 绗?{number}琛岋細璋冪敤涓€涓嚱鏁帮紝鍊熷姪瀹冨畬鎴愬綋鍓嶈繖涓€姝ユ搷浣溿€?*/
AddEdgeAL(dag, 'C', 'E', 1);
/* 绗?{number}琛岋細璋冪敤涓€涓嚱鏁帮紝鍊熷姪瀹冨畬鎴愬綋鍓嶈繖涓€姝ユ搷浣溿€?*/
AddEdgeAL(dag, 'D', 'E', 1);
/* 绗?{number}琛岋細璋冪敤涓€涓嚱鏁帮紝鍊熷姪瀹冨畬鎴愬綋鍓嶈繖涓€姝ユ搷浣溿€?*/
AddEdgeAL(dag, 'E', 'F', 1);
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細杩欐槸鍘熸簮鐮侀噷宸茬粡瀛樺湪鐨勮鏄庢€ф敞閲娿€?*/
/* 构造示例带权无向图:后面用它演示 Prim 最小生成树。 */
/* 绗?{number}琛岋細瀹氫箟鍑芥暟 ㈠紑濮嬪啓瀹冪殑鍏蜂綋瀹炵幇銆?*/
void BuildSampleWeightedUndirectedGraph(AMGraph *graph) {
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
const char *vertices = "ABCDEF";
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細璋冪敤涓€涓嚱鏁帮紝鍊熷姪瀹冨畬鎴愬綋鍓嶈繖涓€姝ユ搷浣溿€?*/
InitAMGraph(graph, vertices, false);
/* 绗?{number}琛岋細璋冪敤涓€涓嚱鏁帮紝鍊熷姪瀹冨畬鎴愬綋鍓嶈繖涓€姝ユ搷浣溿€?*/
AddEdgeAM(graph, 'A', 'B', 6);
/* 绗?{number}琛岋細璋冪敤涓€涓嚱鏁帮紝鍊熷姪瀹冨畬鎴愬綋鍓嶈繖涓€姝ユ搷浣溿€?*/
AddEdgeAM(graph, 'A', 'C', 1);
/* 绗?{number}琛岋細璋冪敤涓€涓嚱鏁帮紝鍊熷姪瀹冨畬鎴愬綋鍓嶈繖涓€姝ユ搷浣溿€?*/
AddEdgeAM(graph, 'A', 'D', 5);
/* 绗?{number}琛岋細璋冪敤涓€涓嚱鏁帮紝鍊熷姪瀹冨畬鎴愬綋鍓嶈繖涓€姝ユ搷浣溿€?*/
AddEdgeAM(graph, 'B', 'C', 5);
/* 绗?{number}琛岋細璋冪敤涓€涓嚱鏁帮紝鍊熷姪瀹冨畬鎴愬綋鍓嶈繖涓€姝ユ搷浣溿€?*/
AddEdgeAM(graph, 'B', 'E', 3);
/* 绗?{number}琛岋細璋冪敤涓€涓嚱鏁帮紝鍊熷姪瀹冨畬鎴愬綋鍓嶈繖涓€姝ユ搷浣溿€?*/
AddEdgeAM(graph, 'C', 'D', 5);
/* 绗?{number}琛岋細璋冪敤涓€涓嚱鏁帮紝鍊熷姪瀹冨畬鎴愬綋鍓嶈繖涓€姝ユ搷浣溿€?*/
AddEdgeAM(graph, 'C', 'E', 6);
/* 绗?{number}琛岋細璋冪敤涓€涓嚱鏁帮紝鍊熷姪瀹冨畬鎴愬綋鍓嶈繖涓€姝ユ搷浣溿€?*/
AddEdgeAM(graph, 'C', 'F', 4);
/* 绗?{number}琛岋細璋冪敤涓€涓嚱鏁帮紝鍊熷姪瀹冨畬鎴愬綋鍓嶈繖涓€姝ユ搷浣溿€?*/
AddEdgeAM(graph, 'D', 'F', 2);
/* 绗?{number}琛岋細璋冪敤涓€涓嚱鏁帮紝鍊熷姪瀹冨畬鎴愬綋鍓嶈繖涓€姝ユ搷浣溿€?*/
AddEdgeAM(graph, 'E', 'F', 6);
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細杩欐槸鍘熸簮鐮侀噷宸茬粡瀛樺湪鐨勮鏄庢€ф敞閲娿€?*/
/* 构造示例带权有向图:后面用它演示 Dijkstra 单源最短路径。 */
/* 绗?{number}琛岋細瀹氫箟鍑芥暟 ㈠紑濮嬪啓瀹冪殑鍏蜂綋瀹炵幇銆?*/
void BuildSampleWeightedDirectedGraph(AMGraph *graph) {
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
const char *vertices = "ABCDE";
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細璋冪敤涓€涓嚱鏁帮紝鍊熷姪瀹冨畬鎴愬綋鍓嶈繖涓€姝ユ搷浣溿€?*/
InitAMGraph(graph, vertices, true);
/* 绗?{number}琛岋細璋冪敤涓€涓嚱鏁帮紝鍊熷姪瀹冨畬鎴愬綋鍓嶈繖涓€姝ユ搷浣溿€?*/
AddEdgeAM(graph, 'A', 'B', 10);
/* 绗?{number}琛岋細璋冪敤涓€涓嚱鏁帮紝鍊熷姪瀹冨畬鎴愬綋鍓嶈繖涓€姝ユ搷浣溿€?*/
AddEdgeAM(graph, 'A', 'C', 3);
/* 绗?{number}琛岋細璋冪敤涓€涓嚱鏁帮紝鍊熷姪瀹冨畬鎴愬綋鍓嶈繖涓€姝ユ搷浣溿€?*/
AddEdgeAM(graph, 'B', 'C', 1);
/* 绗?{number}琛岋細璋冪敤涓€涓嚱鏁帮紝鍊熷姪瀹冨畬鎴愬綋鍓嶈繖涓€姝ユ搷浣溿€?*/
AddEdgeAM(graph, 'B', 'D', 2);
/* 绗?{number}琛岋細璋冪敤涓€涓嚱鏁帮紝鍊熷姪瀹冨畬鎴愬綋鍓嶈繖涓€姝ユ搷浣溿€?*/
AddEdgeAM(graph, 'C', 'B', 4);
/* 绗?{number}琛岋細璋冪敤涓€涓嚱鏁帮紝鍊熷姪瀹冨畬鎴愬綋鍓嶈繖涓€姝ユ搷浣溿€?*/
AddEdgeAM(graph, 'C', 'D', 8);
/* 绗?{number}琛岋細璋冪敤涓€涓嚱鏁帮紝鍊熷姪瀹冨畬鎴愬綋鍓嶈繖涓€姝ユ搷浣溿€?*/
AddEdgeAM(graph, 'C', 'E', 2);
/* 绗?{number}琛岋細璋冪敤涓€涓嚱鏁帮紝鍊熷姪瀹冨畬鎴愬綋鍓嶈繖涓€姝ユ搷浣溿€?*/
AddEdgeAM(graph, 'D', 'E', 7);
/* 绗?{number}琛岋細璋冪敤涓€涓嚱鏁帮紝鍊熷姪瀹冨畬鎴愬綋鍓嶈繖涓€姝ユ搷浣溿€?*/
AddEdgeAM(graph, 'E', 'D', 9);
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細杩欐槸鍘熸簮鐮侀噷宸茬粡瀛樺湪鐨勮鏄庢€ф敞閲娿€?*/
/* 构造示例 AOE 网:后面用它演示关键路径的 ve、vl 和关键活动。 */
/* 绗?{number}琛岋細瀹氫箟鍑芥暟 ㈠紑濮嬪啓瀹冪殑鍏蜂綋瀹炵幇銆?*/
void BuildSampleAOEGraph(ALGraph *graph) {
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
const char *vertices = "ABCDEFG";
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細璋冪敤涓€涓嚱鏁帮紝鍊熷姪瀹冨畬鎴愬綋鍓嶈繖涓€姝ユ搷浣溿€?*/
InitALGraph(graph, vertices, true);
/* 绗?{number}琛岋細璋冪敤涓€涓嚱鏁帮紝鍊熷姪瀹冨畬鎴愬綋鍓嶈繖涓€姝ユ搷浣溿€?*/
AddEdgeAL(graph, 'A', 'B', 3);
/* 绗?{number}琛岋細璋冪敤涓€涓嚱鏁帮紝鍊熷姪瀹冨畬鎴愬綋鍓嶈繖涓€姝ユ搷浣溿€?*/
AddEdgeAL(graph, 'A', 'C', 2);
/* 绗?{number}琛岋細璋冪敤涓€涓嚱鏁帮紝鍊熷姪瀹冨畬鎴愬綋鍓嶈繖涓€姝ユ搷浣溿€?*/
AddEdgeAL(graph, 'B', 'D', 2);
/* 绗?{number}琛岋細璋冪敤涓€涓嚱鏁帮紝鍊熷姪瀹冨畬鎴愬綋鍓嶈繖涓€姝ユ搷浣溿€?*/
AddEdgeAL(graph, 'B', 'E', 3);
/* 绗?{number}琛岋細璋冪敤涓€涓嚱鏁帮紝鍊熷姪瀹冨畬鎴愬綋鍓嶈繖涓€姝ユ搷浣溿€?*/
AddEdgeAL(graph, 'C', 'D', 4);
/* 绗?{number}琛岋細璋冪敤涓€涓嚱鏁帮紝鍊熷姪瀹冨畬鎴愬綋鍓嶈繖涓€姝ユ搷浣溿€?*/
AddEdgeAL(graph, 'C', 'F', 3);
/* 绗?{number}琛岋細璋冪敤涓€涓嚱鏁帮紝鍊熷姪瀹冨畬鎴愬綋鍓嶈繖涓€姝ユ搷浣溿€?*/
AddEdgeAL(graph, 'D', 'G', 2);
/* 绗?{number}琛岋細璋冪敤涓€涓嚱鏁帮紝鍊熷姪瀹冨畬鎴愬綋鍓嶈繖涓€姝ユ搷浣溿€?*/
AddEdgeAL(graph, 'E', 'G', 3);
/* 绗?{number}琛岋細璋冪敤涓€涓嚱鏁帮紝鍊熷姪瀹冨畬鎴愬綋鍓嶈繖涓€姝ユ搷浣溿€?*/
AddEdgeAL(graph, 'F', 'G', 2);
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細瀹氫箟鍑芥暟 ㈠紑濮嬪啓瀹冪殑鍏蜂綋瀹炵幇銆?*/
int main(void) {
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
AMGraph matrix_graph;
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
AMGraph weighted_graph;
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
AMGraph shortest_path_graph;
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
ALGraph list_graph;
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
ALGraph dag;
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
ALGraph aoe_graph;
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
char topo_order[MAX_VERTEX_NUM + 1];
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
int dist[MAX_VERTEX_NUM];
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
int floyd_dist[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
int floyd_path[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
int path[MAX_VERTEX_NUM];
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
int ve[MAX_VERTEX_NUM];
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
int vl[MAX_VERTEX_NUM];
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
bool critical[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
/* 绗?{number}琛岋細澹版槑杩欎竴娈甸€昏緫浼氱敤鍒扮殑灞€閮ㄥ彉閲忋€佹寚閽堟垨缁撴瀯銆?*/
int critical_length;
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細璋冪敤涓€涓嚱鏁帮紝鍊熷姪瀹冨畬鎴愬綋鍓嶈繖涓€姝ユ搷浣溿€?*/
BuildSampleGraphs(&matrix_graph, &list_graph);
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細璋冪敤涓€涓嚱鏁帮紝鍊熷姪瀹冨畬鎴愬綋鍓嶈繖涓€姝ユ搷浣溿€?*/
PrintAMGraph(&matrix_graph);
/* 绗?{number}琛岋細鎶婂綋鍓嶇粨鏋滄墦鍗板嚭鏉ワ紝鏂逛究瑙傚療绋嬪簭杩愯鎯呭喌銆?*/
printf("\n");
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細璋冪敤涓€涓嚱鏁帮紝鍊熷姪瀹冨畬鎴愬綋鍓嶈繖涓€姝ユ搷浣溿€?*/
PrintALGraph(&list_graph);
/* 绗?{number}琛岋細鎶婂綋鍓嶇粨鏋滄墦鍗板嚭鏉ワ紝鏂逛究瑙傚療绋嬪簭杩愯鎯呭喌銆?*/
printf("\n");
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細鎶婂綋鍓嶇粨鏋滄墦鍗板嚭鏉ワ紝鏂逛究瑙傚療绋嬪簭杩愯鎯呭喌銆?*/
printf("DFS by adjacency matrix: ");
/* 绗?{number}琛岋細璋冪敤涓€涓嚱鏁帮紝鍊熷姪瀹冨畬鎴愬綋鍓嶈繖涓€姝ユ搷浣溿€?*/
DFSAM(&matrix_graph);
/* 绗?{number}琛岋細鎶婂綋鍓嶇粨鏋滄墦鍗板嚭鏉ワ紝鏂逛究瑙傚療绋嬪簭杩愯鎯呭喌銆?*/
printf("\n");
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細鎶婂綋鍓嶇粨鏋滄墦鍗板嚭鏉ワ紝鏂逛究瑙傚療绋嬪簭杩愯鎯呭喌銆?*/
printf("BFS by adjacency matrix: ");
/* 绗?{number}琛岋細璋冪敤涓€涓嚱鏁帮紝鍊熷姪瀹冨畬鎴愬綋鍓嶈繖涓€姝ユ搷浣溿€?*/
BFSAM(&matrix_graph);
/* 绗?{number}琛岋細鎶婂綋鍓嶇粨鏋滄墦鍗板嚭鏉ワ紝鏂逛究瑙傚療绋嬪簭杩愯鎯呭喌銆?*/
printf("\n");
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細鎶婂綋鍓嶇粨鏋滄墦鍗板嚭鏉ワ紝鏂逛究瑙傚療绋嬪簭杩愯鎯呭喌銆?*/
printf("DFS by adjacency list: ");
/* 绗?{number}琛岋細璋冪敤涓€涓嚱鏁帮紝鍊熷姪瀹冨畬鎴愬綋鍓嶈繖涓€姝ユ搷浣溿€?*/
DFSAL(&list_graph);
/* 绗?{number}琛岋細鎶婂綋鍓嶇粨鏋滄墦鍗板嚭鏉ワ紝鏂逛究瑙傚療绋嬪簭杩愯鎯呭喌銆?*/
printf("\n");
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細鎶婂綋鍓嶇粨鏋滄墦鍗板嚭鏉ワ紝鏂逛究瑙傚療绋嬪簭杩愯鎯呭喌銆?*/
printf("BFS by adjacency list: ");
/* 绗?{number}琛岋細璋冪敤涓€涓嚱鏁帮紝鍊熷姪瀹冨畬鎴愬綋鍓嶈繖涓€姝ユ搷浣溿€?*/
BFSAL(&list_graph);
/* 绗?{number}琛岋細鎶婂綋鍓嶇粨鏋滄墦鍗板嚭鏉ワ紝鏂逛究瑙傚療绋嬪簭杩愯鎯呭喌銆?*/
printf("\n");
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細鎶婂綋鍓嶇粨鏋滄墦鍗板嚭鏉ワ紝鏂逛究瑙傚療绋嬪簭杩愯鎯呭喌銆?*/
printf("Connected components in sample undirected graph: %d\n",
/* 绗?{number}琛岋細璋冪敤涓€涓嚱鏁帮紝鍊熷姪瀹冨畬鎴愬綋鍓嶈繖涓€姝ユ搷浣溿€?*/
CountConnectedComponentsAM(&matrix_graph));
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細璋冪敤涓€涓嚱鏁帮紝鍊熷姪瀹冨畬鎴愬綋鍓嶈繖涓€姝ユ搷浣溿€?*/
BuildSampleDAG(&dag);
/* 绗?{number}琛岋細杩涜鏉′欢鍒ゆ柇锛屽喅瀹氬綋鍓嶆祦绋嬭蛋鍝釜鍒嗘敮銆?*/
if (TopologicalSortAL(&dag, topo_order)) {
/* 绗?{number}琛岋細鎶婂綋鍓嶇粨鏋滄墦鍗板嚭鏉ワ紝鏂逛究瑙傚療绋嬪簭杩愯鎯呭喌銆?*/
printf("Topological order: %s\n", topo_order);
/* 绗?{number}琛岋細鎵ц杩欎竴琛屼唬鐮侊紝缁х画鎺ㄨ繘褰撳墠閫昏緫銆?*/
} else {
/* 绗?{number}琛岋細鎶婂綋鍓嶇粨鏋滄墦鍗板嚭鏉ワ紝鏂逛究瑙傚療绋嬪簭杩愯鎯呭喌銆?*/
printf("Topological order: graph has a cycle\n");
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細璋冪敤涓€涓嚱鏁帮紝鍊熷姪瀹冨畬鎴愬綋鍓嶈繖涓€姝ユ搷浣溿€?*/
BuildSampleWeightedUndirectedGraph(&weighted_graph);
/* 绗?{number}琛岋細鎶婂綋鍓嶇粨鏋滄墦鍗板嚭鏉ワ紝鏂逛究瑙傚療绋嬪簭杩愯鎯呭喌銆?*/
printf("Prim MST total weight: %d\n", PrimMSTWeightAM(&weighted_graph, 0));
/* 绗?{number}琛岋細鎶婂綋鍓嶇粨鏋滄墦鍗板嚭鏉ワ紝鏂逛究瑙傚療绋嬪簭杩愯鎯呭喌銆?*/
printf("Kruskal MST total weight: %d\n", KruskalMSTWeightAM(&weighted_graph));
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細璋冪敤涓€涓嚱鏁帮紝鍊熷姪瀹冨畬鎴愬綋鍓嶈繖涓€姝ユ搷浣溿€?*/
BuildSampleWeightedDirectedGraph(&shortest_path_graph);
/* 绗?{number}琛岋細璋冪敤涓€涓嚱鏁帮紝鍊熷姪瀹冨畬鎴愬綋鍓嶈繖涓€姝ユ搷浣溿€?*/
DijkstraAM(&shortest_path_graph, 0, dist, path);
/* 绗?{number}琛岋細璋冪敤涓€涓嚱鏁帮紝鍊熷姪瀹冨畬鎴愬綋鍓嶈繖涓€姝ユ搷浣溿€?*/
PrintDijkstraResult(&shortest_path_graph, 0, dist);
/* 绗?{number}琛岋細璋冪敤涓€涓嚱鏁帮紝鍊熷姪瀹冨畬鎴愬綋鍓嶈繖涓€姝ユ搷浣溿€?*/
FloydAM(&shortest_path_graph, floyd_dist, floyd_path);
/* 绗?{number}琛岋細璋冪敤涓€涓嚱鏁帮紝鍊熷姪瀹冨畬鎴愬綋鍓嶈繖涓€姝ユ搷浣溿€?*/
PrintFloydDistances(&shortest_path_graph, floyd_dist);
/* 绗?{number}琛岋細鎶婂綋鍓嶇粨鏋滄墦鍗板嚭鏉ワ紝鏂逛究瑙傚療绋嬪簭杩愯鎯呭喌銆?*/
printf("Floyd path A -> D: ");
/* 绗?{number}琛岋細璋冪敤涓€涓嚱鏁帮紝鍊熷姪瀹冨畬鎴愬綋鍓嶈繖涓€姝ユ搷浣溿€?*/
PrintFloydPathAM(&shortest_path_graph, floyd_path, 0, 3);
/* 绗?{number}琛岋細鎶婂綋鍓嶇粨鏋滄墦鍗板嚭鏉ワ紝鏂逛究瑙傚療绋嬪簭杩愯鎯呭喌銆?*/
printf("Floyd path A -> E: ");
/* 绗?{number}琛岋細璋冪敤涓€涓嚱鏁帮紝鍊熷姪瀹冨畬鎴愬綋鍓嶈繖涓€姝ユ搷浣溿€?*/
PrintFloydPathAM(&shortest_path_graph, floyd_path, 0, 4);
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細璋冪敤涓€涓嚱鏁帮紝鍊熷姪瀹冨畬鎴愬綋鍓嶈繖涓€姝ユ搷浣溿€?*/
BuildSampleAOEGraph(&aoe_graph);
/* 绗?{number}琛岋細杩涜鏉′欢鍒ゆ柇锛屽喅瀹氬綋鍓嶆祦绋嬭蛋鍝釜鍒嗘敮銆?*/
if (CriticalPathAL(&aoe_graph, ve, vl, critical, &critical_length)) {
/* 绗?{number}琛岋細璋冪敤涓€涓嚱鏁帮紝鍊熷姪瀹冨畬鎴愬綋鍓嶈繖涓€姝ユ搷浣溿€?*/
PrintCriticalPathResult(&aoe_graph, ve, vl, critical, critical_length);
/* 绗?{number}琛岋細鎵ц杩欎竴琛屼唬鐮侊紝缁х画鎺ㄨ繘褰撳墠閫昏緫銆?*/
} else {
/* 绗?{number}琛岋細鎶婂綋鍓嶇粨鏋滄墦鍗板嚭鏉ワ紝鏂逛究瑙傚療绋嬪簭杩愯鎯呭喌銆?*/
printf("Critical path: graph has a cycle\n");
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
/* 绗?{number}琛岋細绌鸿锛岀敤鏉ュ垎闅斾笉鍚岀殑灏忔閫昏緫銆?*/
/* 绗?{number}琛岋細璋冪敤涓€涓嚱鏁帮紝鍊熷姪瀹冨畬鎴愬綋鍓嶈繖涓€姝ユ搷浣溿€?*/
DestroyALGraph(&aoe_graph);
/* 绗?{number}琛岋細璋冪敤涓€涓嚱鏁帮紝鍊熷姪瀹冨畬鎴愬綋鍓嶈繖涓€姝ユ搷浣溿€?*/
DestroyALGraph(&dag);
/* 绗?{number}琛岋細璋冪敤涓€涓嚱鏁帮紝鍊熷姪瀹冨畬鎴愬綋鍓嶈繖涓€姝ユ搷浣溿€?*/
DestroyALGraph(&list_graph);
/* 绗?{number}琛岋細鎶婂綋鍓嶅嚱鏁扮殑缁撴灉杩斿洖缁欒皟鐢ㄨ€咃紝骞剁粨鏉熷綋鍓嶅嚱鏁般€?*/
return 0;
/* 绗?{number}琛岋細浠g爜鍧楃粨鏉燂紝褰撳墠杩欎竴灞傞€昏緫鍦ㄨ繖閲屾敹鍙c€?*/
}
继续阅读