数据结构与C语言实现(十)——图(下):Dijkstra与Floyd

来源:互联网 发布:天之道其犹张弓乎原文 编辑:程序博客网 时间:2024/06/07 19:23

1.用BFS实现无权值单源最短路径问题

/*在网络中,求两个不同顶点之间的所有路径中,边的权值之和最小的那一条路径。Shortest PathSource -----》 Destination问题分类:1.单源最短路径问题:从某固定源点触发,求其到所有其他顶点的最短路径。1.1 无权图1.2 有权图2.多源最短路径问题:求任意两顶点间的最短路径*///无权图的单源最短路算法//邻接表#include <stdio.h>#include <stdlib.h>#defineMAXSIZE 100#define INIFITY 65536typedef struct LNode_Vertex* Vertex;typedef struct LNode_Edge* Edge;typedef struct LNode_List* List;typedef struct LNode_Queue* Queue;struct LNode_Vertex{int vex;Edge ptr_edge;};struct LNode_Edge{int adjvex;int weight;Edge next;};//因为邻接表的数据结构是,每个顶点表中的节点都引导出一串边节点struct LNode_Queue{List front;List rear;};struct LNode_List{int data;List next;};LNode_Vertex ver[MAXSIZE];int num_vertex, num_edge;int visited[MAXSIZE];int dist[MAXSIZE];//dist[w] = s到w的最短距离int path[MAXSIZE];//path[w] = S到W的路上经过的某个顶点void Create_Graph(){printf("你要输入的点和边数\n");scanf("%d %d", &num_vertex, &num_edge);printf("下面请输入顶点\n");for (int i = 0; i < num_vertex; i++){scanf("%d", &ver[i].vex);}printf("下面请输入顶点1,顶点2,权值\n");for (int i = 0; i < num_edge; i++){int vex1, vex2, w;scanf("%d %d %d", &vex1, &vex2, &w);Edge E = (Edge)malloc(sizeof(struct LNode_Edge));//建立一个边节点if (ver[vex1].ptr_edge == NULL)ver[vex1].ptr_edge = E;else{Edge p = ver[vex1].ptr_edge;while (p->next != NULL)//直到找到顶点节点所引导的一系列节点的最后{p = p->next;//每次往后移动一位}p->next = E;//将最后一个的next指向E}E->weight = w;E->adjvex = vex2;E->next = NULL;}}void Print_Graph(){for (int i = 0; i < num_vertex; i++){printf("%d——》", ver[i].vex);if (ver[i].ptr_edge != NULL){printf("[%d,%d]->", ver[i].ptr_edge->adjvex, ver[i].ptr_edge->weight);while (ver[i].ptr_edge->next != NULL){printf("[%d,%d]->", ver[i].ptr_edge->next->adjvex, ver[i].ptr_edge->next->weight);ver[i].ptr_edge->next = ver[i].ptr_edge->next->next;}}putchar('\n');}}//为了完成BFS,首先我们需要完成一些关于队列的函数,包括入队和出队Queue CreateQueue(){Queue Q = (Queue)malloc(sizeof(struct LNode_Queue));Q->front = Q->rear = NULL;return Q;}int Is_Empty(Queue Q){if ((Q->front == NULL) && (Q->rear == NULL))return 1;elsereturn 0;}void AddQ(Queue Q, int Item){List L = (List)malloc(sizeof(struct LNode_List));if ((Q->rear == NULL)){Q->front = L;Q->rear = L;L->data = Item;L->next = NULL;}else{Q->rear->next = L;Q->rear = L;L->data = Item;L->next = NULL;}}int ExitQ(Queue Q){List q;if (Q->front == NULL){printf("Error:队列中没有元素可以出队");return -1;}q = Q->front;if (Q->front == Q->rear){Q->front = NULL;Q->rear = NULL;}elseQ->front = Q->front->next;int ans = q->data;free(q);return ans;}void BFS(int S){for (int j = 0; j < MAXSIZE; j++){dist[j] = -1;path[j] = -1;}dist[S] = 0;Queue Q = CreateQueue();AddQ(Q, S);printf("*%d  ", S);while (!Is_Empty(Q)){int V = ExitQ(Q);//j的所有邻边全部入队Edge E = ver[V].ptr_edge;//暂时不去考虑没有邻边的情况do{int W = E->adjvex;if (dist[W] == -1)//如果没被访问过{dist[W] = dist[V] + 1;//j向外扩张一圈的那一圈元素中有k,所有必然距离+1path[W] = V;//前一个顶点是必须要经过的顶点,可以用于打印路径printf("*%d  ", W);AddQ(Q, W);}E = E->next;} while (E != NULL);}for (int i = MAXSIZE -1; i >= 0; i--)if(path[i] != -1)printf("%d  ", path[i]);}int main(){Create_Graph();Print_Graph();putchar('\n');BFS(3);return 0;}/*4 60 1 2 30 3 93 2 80 1 51 3 60 2 72 0 2*/


2.Dijkstra算法下的单源有权值最短路算法

/*在网络中,求两个不同顶点之间的所有路径中,边的权值之和最小的那一条路径。Shortest PathSource -----》 Destination问题分类:1.单源最短路径问题:从某固定源点触发,求其到所有其他顶点的最短路径。1.1 无权图1.2 有权图2.多源最短路径问题:求任意两顶点间的最短路径*///无权图的单源最短路算法//邻接表#include <stdio.h>#include <stdlib.h>#defineMAXSIZE 100#define INIFITY 65536typedef struct LNode_Vertex* Vertex;typedef struct LNode_Edge* Edge;typedef struct LNode_List* List;typedef struct LNode_Queue* Queue;struct LNode_Vertex{int vex;Edge ptr_edge;};struct LNode_Edge{int adjvex;int weight;Edge next;};//因为邻接表的数据结构是,每个顶点表中的节点都引导出一串边节点struct LNode_Queue{List front;List rear;};struct LNode_List{int data;List next;};LNode_Vertex ver[MAXSIZE];int num_vertex, num_edge;int visited[MAXSIZE];int dist[MAXSIZE];//dist[w] = s到w的最短距离int path[MAXSIZE];//path[w] = S到W的路上经过的某个顶点void Create_Graph(){printf("你要输入的点和边数\n");scanf("%d %d", &num_vertex, &num_edge);printf("下面请输入顶点\n");for (int i = 0; i < num_vertex; i++){scanf("%d", &ver[i].vex);}printf("下面请输入顶点1,顶点2,权值\n");for (int i = 0; i < num_edge; i++){int vex1, vex2, w;scanf("%d %d %d", &vex1, &vex2, &w);Edge E = (Edge)malloc(sizeof(struct LNode_Edge));//建立一个边节点if (ver[vex1].ptr_edge == NULL)ver[vex1].ptr_edge = E;else{Edge p = ver[vex1].ptr_edge;while (p->next != NULL)//直到找到顶点节点所引导的一系列节点的最后{p = p->next;//每次往后移动一位}p->next = E;//将最后一个的next指向E}E->weight = w;E->adjvex = vex2;E->next = NULL;}}void Print_Graph(){for (int i = 0; i < num_vertex; i++){printf("%d——》", ver[i].vex);if (ver[i].ptr_edge != NULL){printf("[%d,%d]->", ver[i].ptr_edge->adjvex, ver[i].ptr_edge->weight);while (ver[i].ptr_edge->next != NULL){printf("[%d,%d]->", ver[i].ptr_edge->next->adjvex, ver[i].ptr_edge->next->weight);ver[i].ptr_edge->next = ver[i].ptr_edge->next->next;}}putchar('\n');}}//为了完成BFS,首先我们需要完成一些关于队列的函数,包括入队和出队Queue CreateQueue(){Queue Q = (Queue)malloc(sizeof(struct LNode_Queue));Q->front = Q->rear = NULL;return Q;}int Is_Empty(Queue Q){if ((Q->front == NULL) && (Q->rear == NULL))return 1;elsereturn 0;}void AddQ(Queue Q, int Item){List L = (List)malloc(sizeof(struct LNode_List));if ((Q->rear == NULL)){Q->front = L;Q->rear = L;L->data = Item;L->next = NULL;}else{Q->rear->next = L;Q->rear = L;L->data = Item;L->next = NULL;}}int ExitQ(Queue Q){List q;if (Q->front == NULL){printf("Error:队列中没有元素可以出队");return -1;}q = Q->front;if (Q->front == Q->rear){Q->front = NULL;Q->rear = NULL;}elseQ->front = Q->front->next;int ans = q->data;free(q);return ans;}void BFS(int S){for (int j = 0; j < MAXSIZE; j++){dist[j] = -1;path[j] = -1;}dist[S] = 0;Queue Q = CreateQueue();AddQ(Q, S);printf("*%d  ", S);while (!Is_Empty(Q)){int V = ExitQ(Q);//j的所有邻边全部入队Edge E = ver[V].ptr_edge;//暂时不去考虑没有邻边的情况do{int W = E->adjvex;if (dist[W] == -1)//如果没被访问过{dist[W] = dist[V] + 1;//j向外扩张一圈的那一圈元素中有k,所有必然距离+1path[W] = V;//前一个顶点是必须要经过的顶点,可以用于打印路径printf("*%d  ", W);AddQ(Q, W);}E = E->next;} while (E != NULL);}for (int i = MAXSIZE -1; i >= 0; i--)if(path[i] != -1)printf("%d  ", path[i]);}int main(){Create_Graph();Print_Graph();putchar('\n');BFS(3);return 0;}/*4 60 1 2 30 3 93 2 80 1 51 3 60 2 72 0 2*/


3. Floyd算法下多源最短路径

/*算法描述1)算法思想原理:Floyd算法是一个经典的动态规划算法。用通俗的语言来描述的话,首先我们的目标是寻找从点i到点j的最短路径。从动态规划的角度看问题,我们需要为这个目标重新做一个诠释(这个诠释正是动态规划最富创造力的精华所在)从任意节点i到任意节点j的最短路径不外乎2种可能,1是直接从i到j,2是从i经过若干个节点k到j。所以,我们假设Dis(i,j)为节点u到节点v的最短路径的距离,对于每一个节点k,我们检查Dis(i,k) + Dis(k,j) < Dis(i,j)是否成立,如果成立,证明从i到k再到j的路径比i直接到j的路径短,我们便设置Dis(i,j) = Dis(i,k) + Dis(k,j),这样一来,当我们遍历完所有节点k,Dis(i,j)中记录的便是i到j的最短路径的距离。2).算法描述:a.从任意一条单边路径开始。所有两点之间的距离是边的权,如果两点之间没有边相连,则权为无穷大。   b.对于每一对顶点 u 和 v,看看是否存在一个顶点 w 使得从 u 到 w 再到 v 比己知的路径更短。如果是更新它。*//* 邻接矩阵表示的图结构 */#include <stdio.h>#include <stdlib.h>typedef int VertexType;typedef intEdgeType;#define MAXVEX 100#define INFINITY 65535#define DEBUGint path[MAXVEX][MAXVEX];typedef struct{VertexType vexs[MAXVEX];//顶点表,用来存放顶点数目EdgeType   arc[MAXVEX][MAXVEX];//邻接矩阵,边int numVertexes, numEdges;}Graph;//在图中寻找某个顶点int Find_Vertex(Graph *g, char ch){int i = 0;for (i = 0; i < g->numVertexes; i++){if (g->vexs[i] == ch)break;}return i;}void CreateGraph(Graph* G){printf("请输入顶点和边数:\n");scanf("%d %d", &G->numVertexes, &G->numEdges);#ifdef DEBUGprintf("%d %d\n", G->numVertexes, G->numEdges);#endif // DEBUGprintf("请输入顶点值:\n");for (int i = 0; i < G->numVertexes; i++){scanf("%d", &G->vexs[i]);}//有向网络逆向值为无穷,正向值为权值,自己到自己为0//无向网络不连接为0,有连接为权值for (int i = 0; i < G->numVertexes; i++){for (int j = 0; j < G->numVertexes; j++)G->arc[i][j] = INFINITY;}printf("输入<vi,vj>的两个顶点标号,和权值.\n按Q表示退出\n");while (getchar() != 'q'){int m, n, w;scanf("%d %d %d", &m, &n, &w);G->arc[m][n] = w;G->arc[n][m] = w;}}void Floyd(Graph *G){int i, j, k;int F[MAXVEX][MAXVEX];//先初始化矩阵for (i = 0; i < G->numVertexes; i++)for (j = 0; j < G->numVertexes; j++){F[i][j] = G->arc[i][j];path[i][j] = -1;}for (k = 0; k < G->numVertexes; k++)for (i = 0; i < G->numVertexes; i++)for (j = 0; j < G->numVertexes; j++)if ((F[i][k] + F[k][j]) < F[i][j]){F[i][j] = F[i][k] + F[k][j];path[i][j] = k;}}void Print_Graph(Graph *G){for (int i = 0; i < G->numVertexes; i++){for (int j = 0; j < G->numVertexes; j++){printf("%d ", G->arc[i][j]);}putchar('\n');}}int main(){Graph New_Graph;Graph *G = &New_Graph;CreateGraph(G);Print_Graph(G);return 0;}


阅读全文
0 0
原创粉丝点击