Floyd算法 数据结构 浙江大学 陈越、何钦铭

算法主体就是老师给的,自己把它写完,能跑起来。能在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);
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值