算法主体就是老师给的,自己把它写完,能跑起来。能在visual studio 2022上跑起来。
#include <stdio.h>
#include <stdlib.h>
//#include <string.h>
#include <assert.h>
#include <stdbool.h>
#include <limits.h>
typedef int distance;
typedef int Vertex;
struct Graph
{
int VertexN;
distance* AdjM;
};
distance* Creat2D(int row, int col)
{
/*row col >= 1;先行 后列*/
/*这是我能想到的,最好的办法*/
distance* d = (distance*)malloc(sizeof(distance) * col * row);
return d;
}
distance* BuildGraph(struct Graph * g)
{
int VertexN;
puts("输入顶点的个数VertexN:");
scanf_s("%d", &VertexN);
distance* d = Creat2D(VertexN, VertexN);
for (int i = 0; i != VertexN * VertexN; ++i)
{
if (&d[i])
{
d[i] = INT_MAX;
}
}
puts("输入顶点i,顶点j,还有从i到j的距离;i==j 结束输入");
int i = 0, j = i + 1; distance dist;
while (i != j)
{
//不检查bug;
scanf_s("%d%d%d", &i, &j, &dist);
if (&d[i * VertexN + j])
{
d[i * VertexN + j] = dist;
}
}
for (int i_1 = 0; i_1 != VertexN; ++i_1)
{
if (&d[i_1 * VertexN + i_1])
{
d[i_1 * VertexN + i_1] = 0;
}
}
g->AdjM = d;
g->VertexN = VertexN;
return d;
}
bool Floyd(struct Graph* g,distance* D, Vertex* Path)
{
Vertex VertexN = g->VertexN;
for (int i = 0; i != VertexN * VertexN; ++i)
{
if (&D[i] && &Path[i])
{
D[i] = g->AdjM[i];
Path[i] = -1;
}
else
{
assert(0);
return false;
}
}
Vertex i, j, k;
for (k = 0; k < g->VertexN; k++)
for (i = 0; i < g->VertexN; i++)
for (j = 0; j < g->VertexN; j++)
{
if (D[i * VertexN + k]==INT_MAX|| D[k * VertexN + j] == INT_MAX)
{
continue;
}
if (D[i * VertexN + k] + D[k * VertexN + j] < D[i * VertexN + j]) {
D[i * VertexN + j] = D[i * VertexN + k] + D[k * VertexN + j];
if (i == j && D[i * VertexN + j] < 0) /* 若发现负值圈 */
return false; /* 不能正确解决,返回错误标记 */
Path[i * VertexN + j] = k;
/*我觉得这个算法这样写有问题,因为,无边表示为无穷大,但是无穷大加一就是负数,所以
这个算法可能是有问题的。*/
}
}
return true; /* 算法执行完毕,返回正确标记 */
}
void show_matrix(int* d,int col,int row)
{
for (int i = 0; i != row; ++i)
{
for (int j = 0; j != col; ++j)
{
printf("\t%d", d[i * col + j]);
}
printf("\n");
}
}
typedef Vertex ListElement;
struct ListNode
{
ListElement E;
struct ListNode* pre;
struct ListNode* next;
};
struct List
{
struct ListNode head;
struct ListNode tail;
};
void InitialList(struct List*L)
{
L->head.pre = NULL;
L->head.E = INT_MIN;
L->head.next = &(L->tail);
L->tail.next = NULL;
L->tail.E = INT_MIN;
L->tail.pre = &(L->head);
}
bool Insert2List(struct ListNode* H, struct ListNode* T, ListElement E)
{
if (H == NULL || T == NULL) {return false;}
if (H->next != T || T->pre != H) { return false; }
struct ListNode* L = (struct ListNode*)malloc(sizeof(struct ListNode));
if(L!=NULL){
L->E = E;
L->pre = H;
L->next = T;
H->next = L;
T->pre = L;
}
return true;
}
//还差一个show_path() 双向链表已经构造好了。
void give_path(Vertex* Path,int VertexN,struct ListNode* H, struct ListNode* T, Vertex i,Vertex j)
{
Vertex k=Path[i*VertexN+j];
if (k >= 0 && k < VertexN)
{
Insert2List(H, T, k);
give_path(Path, VertexN, H, T->pre, i, k);
give_path(Path, VertexN, T->pre, T, k, j);//H->next 可能已经不是正确的头节点了,所以不能用,必须用
//T->pre。
}
}
void Give_Path(Vertex* Path, int VertexN, struct List* L, Vertex i, Vertex j)
{
struct ListNode* H = &(L->head);
struct ListNode* T = &(L->tail);
//不检查出格的bug
if (i == j) {
Insert2List(H, T, i);
return;
}
else
{
Insert2List(H, T, i);
H = H->next;
Insert2List(H, T, j);
T = T->pre;
}
give_path(Path, VertexN, H, T, i, j);
}
void Show_List(struct List* L)
{
struct ListNode* H = L->head.next;
while (H != NULL)
{
if (H->E >= 0) {
printf("\t%d", H->E);
}
H = H->next;
}
}
int main()
{
struct Graph g;
BuildGraph(&g);
distance* dist= (distance*)malloc(sizeof(distance) * g.VertexN * g.VertexN);
Vertex* Path = (distance*)malloc(sizeof(Vertex) * g.VertexN * g.VertexN);
Floyd(&g, dist, Path);
puts("dist");
show_matrix(dist, g.VertexN, g.VertexN);
puts("Path");
show_matrix(Path, g.VertexN, g.VertexN);
int a, b;
//没有管理内存,试验次数过多会内存溢出。
while (true) {
puts("\n请输入起点a,终点b,输入负数会结束该循环");
scanf_s("%d %d", &a, &b);
if (a < 0) break;
struct List L;
InitialList(&L);
Give_Path(Path, g.VertexN, &L, a, b);
puts("从a到b的路径:");
Show_List(&L);
}
}