弗洛伊德算法实验
弗洛伊德算法解析见弗洛伊德算法
采用邻接矩阵存储图,矩阵的行和列为图的节点,矩阵的内容为图的权重。
//#pragma comment(linker,"/STACK:614400000,614400000")
//在运行PRINT_ALL_PAIRS_SHORTEST_PATH的时候如果发生stack overflow,请使用上一行的语句扩展栈
#define INF 999999999//无穷大定义
#define NIL -1//Pi矩阵的不可达定义
#define _CRT_SECURE_NO_DEPRECATE
#define frow 11484 //这里是我的图的行数,改成自己图的行数即可
#define N 1000 //这是我节点的数量,改成自己节点的数量即可
#include <iostream>
#include<fstream>
#include<stdio.h>
#include<string>
using namespace std;
int* read(string filename, int n) {
ifstream fp(filename, ios::in);
int p1, p2, weight; //数据缓冲区
int *MAT = new int[n * n];
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
MAT[i * n + j] = INF;
if (i == j)MAT[i * n + j] = 0;
}
}
if (!fp) { // 判断文件是否存在
cerr << "open error." << endl;
return nullptr;
}
for (int i = 0; i < frow; i++) {
fp >> p1;
fp >> p2;
fp >> weight;
//cout << p1 << " " << p2 << " " << weight << endl;
if (p1 < 0 || p1>1000 || p2 < 0 || p2>1000) {
throw"读取数据错误";
}
MAT[p1 * n + p2] = weight;
}
return MAT;
}
void write(string filename, int* MAT,int n) {
ofstream fout(filename, ios::out);
if (!fout) { // 判断文件是否存在
cerr << "open error." << endl;
//exit(1); // 退出程序
}
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++){
if (MAT[i * n + j] == INF)fout << "INF" << ",";
else fout << MAT[i * n + j] << ",";
}
fout << endl;
}
fout.close();
}
void print(int *D, int n) {
//打印矩阵
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (D[i * n + j] == INF)cout << "INF ";
else
cout << D[i*n+j]<<" ";
}
cout << endl;
}
}
int** FLOYD_WARSHALL(int* W, int n) {
int* D;
int* PI;
int** res = new int* [2];
D = new int [n*n];
PI = new int[n * n];
res[0] = D;
res[1] = PI;
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (W[i * n + j] == INF || i == j)PI[i * n + j] = NIL;
else PI[i * n + j] = i;
D[i * n + j] = W[i * n + j];
}
}//初始化D矩阵
for (int k = 0; k < n; k++)
{
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
if (D[i * n + j] > D[i * n + k] + D[k * n + j]) {
PI[i * n + j] = PI[k * n + j];
D[i * n + j] = D[i * n + k] + D[k * n + j];
}
}
}
printf("正在运算%d/%d\r", k+1,n);
}
return res;
}
void PRINT_ALL_PAIRS_SHORTEST_PATH(int *PI,int i,int j) {
if (i == j) {
cout << i<<" ";
}
else if (PI[i*N+j] == NIL) {
cout << "No path from " << i << " to " << j << " exits" << endl;
}
else
{
PRINT_ALL_PAIRS_SHORTEST_PATH(PI, i, PI[i * N + j]);
cout << j<<" ";
}
}
int main() {
/*int W[25] = { 0 ,3 ,8 ,INF,-4,INF,0 ,INF,1 ,7 ,INF,4 ,0 ,INF,INF,2 ,INF,-5 ,0 ,INF,INF,INF,INF,6 ,0 };
//print(W,5);
//cout << endl;
int** res;
res = FLOYD_WARSHALL(W, 5);
print(res[0], 5);
cout << endl;
print(res[1], 5);
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 5; j++) {
cout << "从" << i << "到" << j << "的最短路径为:" << endl;
PRINT_ALL_PAIRS_SHORTEST_PATH(res[1], i, j, 5);
cout << endl;
}
}
delete[]res;*/
/*ifstream fp("weight_graph.txt", ios::in);
string buff;
int p1, p2, weight; //数据缓冲区
int* W = new int[N*N];
int** res;
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
W[i * N + j] = INF;
if (i == j)W[i * N + j] = 0;
}
}
if (!fp) { // 判断文件是否存在
cerr << "open error." << endl;
return 1;
}
for (int i = 0; i < 11484; i++) {
for (int j = 0; j < 3; j++) {
if (j == 0)fp >> p1;
else if (j == 1)fp >> p2;
else fp >> weight;
}
//cout << p1 << " " << p2 << " " << weight << endl;
W[p1 * N + p2] = weight;
}
*/
int* W;
int** res;
W = read("weight_graph.txt", N);
res = FLOYD_WARSHALL(W,N);
//for (int i = 0; i < N; i++) {
//for (int j = 0; j < N; j++) {
//PRINT_ALL_PAIRS_SHORTEST_PATH(res[1], i, j);
//cout << endl;
//}
//}
cout << "正在存储D矩阵" << endl;
write("D-result.txt", res[0],N);
cout << "D矩阵存储完成" << endl;
cout << "正在存储Pi矩阵" << endl;
write("Pi-result.txt", res[1], N);
cout << "Pi矩阵存储完成" << endl;
if (W != nullptr) {
delete[]W;
}
if (res != nullptr) {
delete[]res;
}
/*ofstream dout("D-result.txt", ios::out);
ofstream pout("Pi-result.txt", ios::out);
string D;
string Pi;
if (!dout) { // 判断文件是否存在
cerr << "open error." << endl;
//exit(1); // 退出程序
}
if (!pout) { // 判断文件是否存在
cerr << "open error." << endl;
//exit(1); // 退出程序
}
dout << result[0];
dout << result[1];
fp.close();
dout.close();
pout.close();*/
return 0;
}