参考王道《2023年数据结构考研复习指导》
一、单源最短路径-无权图-BFS最短路径#include二、Dijkstra算法#define MaxVerTexNum 20 typedef char VertexType; // 顶点的数据类型 typedef int EdgeType; // 带权图中边上权值的数据类型 // 邻接矩阵存储图 typedef struct { VertexType Vex[MaxVerTexNum]; // 顶点表 EdgeType Edge[MaxVerTexNum][MaxVerTexNum]; // 邻接矩阵,边表 int vexnum, arcnum; // 图的当前顶点数和边数/弧数 } MGraph; // 链式队列结点 typedef struct LinkNode { int data; // 存储图的顶点的下标 struct LinkNode* next; } LinkNode; // 链式队列 typedef struct LinkQueue { LinkNode* front, * rear; } LinkQueue; bool visited[MaxVerTexNum]; // 已访问标志数组 int d[MaxVerTexNum]; // 记录每个顶点到u的最短路径长度 int path[MaxVerTexNum]; // 记录每个顶点在广度优先生成树中的父节点 bool InitQueue(LinkQueue& Q); bool IsEmpty(LinkQueue Q); bool EnQueue(LinkQueue& Q, int x); bool DeQueue(LinkQueue& Q, int& x); void DestroyQueue(LinkQueue& Q); int FirstNeighbor(MGraph G, int x); int NextNeighbor(MGraph G, int x, int y); void BFS_MIN_Distance(MGraph G, int u); int main() { MGraph G = { {'1', '2', '3', '4', '5', '6', '7', '8'}, { {0,1,0,0,1,0,0,0}, {1,0,0,0,0,1,0,0}, {0,0,0,1,0,1,1,0}, {0,0,1,0,0,0,1,1}, {1,0,0,0,0,0,0,0}, {0,1,1,0,0,0,1,0}, {0,0,1,1,0,1,0,1}, {0,0,0,1,0,0,1,0}, }, 8, 10 }; BFS_MIN_Distance(G, 1); for (int i = 0; i < G.vexnum; ++i) { std::cout << d[i] << " "; } std::cout << std::endl; for (int i = 0; i < G.vexnum; ++i) { std::cout << path[i] << " "; } std::cout << std::endl; system("pause"); return 0; } // 初始化队列(带头结点) bool InitQueue(LinkQueue& Q) { Q.front = Q.rear = (LinkNode*)malloc(sizeof(LinkNode)); if (Q.front == NULL) return false; Q.front->next = NULL; return true; } // 判断队列是否为空 bool IsEmpty(LinkQueue Q) { if (Q.front == Q.rear) return true; else return false; } // 入队(带头结点) bool EnQueue(LinkQueue& Q, int x) { LinkNode* s = (LinkNode*)malloc(sizeof(LinkNode)); if (s == NULL) return false; s->data = x; s->next = NULL; Q.rear->next = s; Q.rear = s; return true; } // 出队(带头结点) bool DeQueue(LinkQueue& Q, int& x) { if (IsEmpty(Q)) return false; LinkNode* p = Q.front->next; x = p->data; Q.front->next = p->next; if (p == Q.rear) // 若此时是最后一个结点出队 Q.rear = Q.front; free(p); return true; } void DestroyQueue(LinkQueue& Q) { LinkNode* p = Q.front->next; LinkNode* q; while (p != NULL) { q = p; p = p->next; free(q); } free(Q.front); Q.front = Q.rear = NULL; } // 求图G中顶点x(下标)的第一个邻接点,若有则返回顶点号。若x没有邻接点或图中不存在x,则返回-1 int FirstNeighbor(MGraph G, int x) { if (x >= G.vexnum) return -1; int i = 0; while (i < G.vexnum) { if (G.Edge[x][i] != 0) return i; i++; } return -1; } // 假设图G中顶点y是顶点x的一个邻接点,返回除y之外顶点x的下一个邻接点的顶点号,若y是x的最后一个邻接点,则返回-1 int NextNeighbor(MGraph G, int x, int y) { if (x >= G.vexnum || y >= G.vexnum) return -1; int i = y + 1; while (i < G.vexnum) { if (G.Edge[x][i] != 0) return i; i++; } return -1; } // 求顶点u到其他顶点的最短路径 void BFS_MIN_Distance(MGraph G, int u) { // 从顶点u出发,广度优先遍历图G for (int i = 0; i < G.vexnum; ++i) { d[i] = -1; // -1代表无穷大 path[i] = -1; // 最短路径从哪个定点过来 } d[u] = 0; visited[u] = true; LinkQueue Q; InitQueue(Q); EnQueue(Q, u); // 顶点u入队列Q while (!IsEmpty(Q)) { DeQueue(Q, u); // 顶点u出队列 for (int w = FirstNeighbor(G, u); w >= 0; w = NextNeighbor(G, u, w)) { //检测v所有邻接点 if (!visited[w]) { // w为v的尚未访问的邻接点 d[w] = d[u] + 1; // 路径长度加1 path[w] = u; // 最短路径应从u到w visited[w] = true; // 对w做已访问标记 EnQueue(Q, w); // 顶点w入队 } } } DestroyQueue(Q); }
#include三、Floyd算法#define MaxVerTexNum 20 typedef char VertexType; // 顶点的数据类型 typedef int EdgeType; // 带权图中边上权值的数据类型 // 邻接矩阵存储图 typedef struct { VertexType Vex[MaxVerTexNum]; // 顶点表 EdgeType Edge[MaxVerTexNum][MaxVerTexNum]; // 邻接矩阵,边表 int vexnum, arcnum; // 图的当前顶点数和边数/弧数 } MGraph; bool final[MaxVerTexNum]; // 标记各顶点是否已找到最短路径 EdgeType dist[MaxVerTexNum]; // 最短路径长度 int path[MaxVerTexNum]; // 路径上的前驱(记录前驱节点的下标) void ShortestPath_Dijkstra(MGraph G, int u); void get_Path(int u, int v); void find_Path(int v); int main() { MGraph G = { {'0', '1', '2', '3', '4'}, { {-1, 10, -1, -1, 5}, {-1, -1, 1, -1, 2}, {-1, -1, -1, 4, -1}, {7, -1, 6, -1, -1}, {-1, 3, 9, 2, -1} }, 5, 10 }; ShortestPath_Dijkstra(G, 0); get_Path(0, 2); system("pause"); return 0; } // 从顶点u出发,到其他结点的最短路径 void ShortestPath_Dijkstra(MGraph G, int u) { for (int i = 0; i < G.vexnum; ++i) { // 初始化辅助数组 final[i] = false; dist[i] = G.Edge[u][i]; path[i] = G.Edge[u][i] == -1 ? -1 : 0; } final[u] = true; dist[u] = 0; // 顶点u到自身的最短距离为0 for (int i = 0; i < G.vexnum; ++i) { if (i == u) continue; int min = -1; // -1代表无穷大 int v; // 下一个已找到最短路径的结点 for (int j = 0; j < G.vexnum; ++j) { if (final[j] == false) { if (min == -1 && dist[j] != -1) { v = j; min = dist[j]; } else if (min != -1 && dist[j] != -1 && dist[j] < min) { v = j; min = dist[j]; } } } final[v] = true; for (int j = 0; j < G.vexnum; ++j) { // 更新dist和path信息 if (final[j] == false) { if (dist[j] == -1 && G.Edge[v][j] != -1) { dist[j] = dist[v] + G.Edge[v][j]; path[j] = v; } else if (dist[j] != -1 && G.Edge[v][j] != -1 && dist[j] > dist[v] + G.Edge[v][j]) { dist[j] = dist[v] + G.Edge[v][j]; path[j] = v; } } } } } void get_Path(int u, int v) { std::cout << "从" << u << "到" << v << "的最短距离为:" << dist[v] << std::endl << "路径为:"; find_Path(v); std::cout << std::endl; } void find_Path(int v) { if (path[v] == -1) { std::cout << v; } else { find_Path(path[v]); std::cout << " -> " << v; } }
#include#define MaxVerTexNum 20 typedef char VertexType; // 顶点的数据类型 typedef int EdgeType; // 带权图中边上权值的数据类型 // 邻接矩阵存储图 typedef struct { VertexType Vex[MaxVerTexNum]; // 顶点表 EdgeType Edge[MaxVerTexNum][MaxVerTexNum]; // 邻接矩阵,边表 int vexnum, arcnum; // 图的当前顶点数和边数/弧数 } MGraph; int A[MaxVerTexNum][MaxVerTexNum]; // 各顶点间的最短路径长度 int path[MaxVerTexNum][MaxVerTexNum]; // 两顶点之间的中转点 void ShortestPath_Floyd(MGraph G); void get_Path(int u, int v); void find_Path(int u, int v); int main() { MGraph G = { {'0', '1', '2', '3', '4'}, { {-1, -1, 1, -1, 10}, {-1, -1, -1, 1, 5}, {-1, 1, -1, -1, 7}, {-1, -1, -1, -1, 1}, {-1, -1, -1, -1, -1}, }, 5, 7 }; ShortestPath_Floyd(G); get_Path(0, 4); system("pause"); return 0; } void ShortestPath_Floyd(MGraph G) { for (int i = 0; i < G.vexnum; ++i) { for (int j = 0; j < G.vexnum; ++j) { A[i][j] = G.Edge[i][j]; path[i][j] = -1; } } for (int k = 0; k < G.vexnum; ++k) { // 以Vk作为中转点 for (int i = 0; i < G.vexnum; ++i) { for (int j = 0; j < G.vexnum; ++j) { if (A[i][j] == -1 && A[i][k] != -1 && A[k][j] != -1) { A[i][j] = A[i][k] + A[k][j]; path[i][j] = k; } else if (A[i][j] != -1 && A[i][k] != -1 && A[k][j] != -1 && A[i][j] > A[i][k] + A[k][j]) { A[i][j] = A[i][k] + A[k][j]; path[i][j] = k; } } } } } void get_Path(int u, int v) { std::cout << "从" << u << "到" << v << "的最短距离为:" << A[u][v] << std::endl << "路径为:"; std::cout << u << " -> "; find_Path(u, v); std::cout << v << std::endl; } void find_Path(int u, int v) { if (path[u][v] != -1) { find_Path(u, path[u][v]); std::cout << path[u][v] << " -> "; find_Path(path[u][v], v); } }



