数据结构–图(最短路径、深度优先遍历、邻接表的创建)
要求是将两个csv文件读取,分别包含城市的数据(名字,经纬度,国家等)和路线数据(出发城市,目的地,价格,时间等)。然后实现深度遍历,最短路径算法。
![在这里插入图片描述](https://img-blog.csdnimg.cn/20200509201103916.png)
![在这里插入图片描述](https://img-blog.csdnimg.cn/2020050920111428.png)
首先创建相关结构体
#include<iostream>
#include<math.h>
#include<Windows.h>
#include<cstdlib>
using namespace std;
#define MAX 222
#define OK 1
float a[MAX][MAX];
typedef struct{
float latitude;
float longitude;
}VerTexType;
typedef struct{
string transport, other_information;
float time, cost;//即边的权
}OtherInfo;//边结点
typedef struct Route{
int adjvex;
string next;//该边所指向的顶点的位置
struct Route* nextarc;//指向下一条边的指针
OtherInfo info;//和边相关的信息
}Route;//顶点信息
typedef struct{
VerTexType data;
int tag;
bool pass;
string country;
string city;
Route* firstdes;
}City, Cities[MAX];//邻接表
typedef struct{
Cities cities;
int vexnum, arcnum;//图的当前顶点数和边数
}ALGraph;
接下来建图读文件(我是边建边读)
//找元素所处位置
int LocateVex(ALGraph G, string u){
for (int i = 0; i < G.vexnum; i++) {
if (u == G.cities[i].city)//好像不能用strcm
return i;
}
return -1;
}
//构建有向图(by CSV)邻接表
string v1[2000], v2[2000];
int Create(ALGraph& G){
//确定顶点数和边数
G.arcnum = 1975;
G.vexnum = 199;
//输入各点,构造表头结点表
FILE* fp;
fopen_s(&fp,"E:\\数据结构练习\\实习1图\\RRoute\\RRoute\\cities. csv", "r") ;
if (!fp)
{
printf("Error!\n");
exit(0);
}
char ch;
float f;
int i = 0;
while (!feof(fp) && i < G.vexnum)
{
ch = fgetc(fp);
for (; ch != ','; ch = fgetc(fp))
{
G.cities[i].country += ch;
}
ch = fgetc(fp);
for (; ch != ','; ch = fgetc(fp))
{
G.cities[i].city += ch;
}
fscanf_s(fp, "%f,", &f); G.cities[i].data.latitude = f; fscanf_s(fp, "%f,", &f); G.cities[i].data.longitude = f; G.cities[i].tag = i; G.cities[i].firstdes = NULL; ch = fgetc(fp);
i++; }
fclose(fp);
//构造邻接表
FILE* fp1;
fopen_s(&fp1,"E:\\数据结构练习\\test\\routes.csv", "r");
if (!fp1)
{
printf("Error!\n");
exit(0);
}
char ch1;
float f1;
int m = 0, n = 0;
i = 0;
while (!feof(fp) && i < G.arcnum)
{
ch1 = fgetc(fp1);
for (; ch1 != ','; ch1 = fgetc(fp1))
{
v1[i] += ch1;
}
ch1 = fgetc(fp1);
for (; ch1 != ','; ch1 = fgetc(fp1))
{
v2[i] += ch1;
}
m = LocateVex(G, v1[i]), n = LocateVex(G, v2[i]);
Route* p1 = new Route;//生成一个新的边结点*p1
ch1 = fgetc(fp1); //完善边界点的信息
for (; ch1 != ','; ch1 = fgetc(fp1))
{
p1->info.transport += ch1;
}//交通方式
fscanf_s(fp1, "%f,", &f1);
p1->info.time = f1;//时间
fscanf_s(fp1, "%f,", &f1);
p1->info.cost = f1;//价格
ch1 = fgetc(fp1);
ch1 = fgetc(fp1);
for (; ch1 != '"'; ch1 = fgetc(fp1))
{
p1->info.other_information += ch1;
}//其他信息
p1->adjvex = n;//邻接点序号为n
p1->nextarc = G.cities[m].firstdes;
G.cities[m].firstdes = p1;
i++;
ch1 = fgetc(fp1);
}
fclose(fp1);
return OK;
}
然后就做深度优先遍历
int whether[MAX] = { 0 };
void DFS(ALGraph* G, int i)
{
whether[i] = 1;
cout << G->cities[i].city << "-->";
Route* p = G->cities[i].firstdes;
while (p)
{
if (whether[p->adjvex] == 0)
DFS(G, p->adjvex);
p = p->nextarc;
}
}
呜呜呜,接下来就是快乐的最短路径了,要求做迪杰斯特拉算法
由于本人技术有限,只会做邻接矩阵的算法,所以我只能将表里面需要用到的数据先转成一个矩阵。QwQ
void trans(ALGraph G)
{
int i, j;
Route* p;
for (i = 0; i <= G.vexnum; i++)//先初始化,全部赋值为9999
{
for (j = 0; j <= G.vexnum; j++)
{
a[i][j] = 9999;
}
}
for (i = 0; i < G.vexnum; i++)
{
p = G.cities[i].firstdes;
while (p)
{
if (a[i][p->adjvex] > p->info.cost)//确保a中为最小值
{
a[i][p->adjvex] = p->info.cost;
}
p = p->nextarc;
}
}
}
接下来就可以进行了(●°u°●) 」
void Dijkstra(ALGraph G, float dist[][MAX])
{
int depart, dest;
string v, u;
int from[MAX] = { 0 };
//确定出发点和目的地
cout << "从 到 :";
cin >> v >> u;
depart = LocateVex(G, v);
dest = LocateVex(G, u);
G.cities[depart].pass = true;
//将pass初始化,并将cost的数据拷入dist里面
for (int v = 0; v < G.vexnum; v++)
{
G.cities[v].pass = false;
for (int h = 0; h < G.vexnum; h++)
{
dist[v][h] = a[v][h];
}
from[v] = depart;
dist[v][v] = 0;
}
//找最短路径
for (int i = 0; i < G.vexnum; i++)
{
int v = 0;
double mincost = 9999;
//find the point that is closest to the depart
for (int w = 0; w < G.vexnum; w++)
{
if (G.cities[w].pass == false)
if (dist[depart][w] < mincost)
{
v = w;
mincost = dist[depart][w];//将最短距离copy到mincost里
}
}
//update the dist
G.cities[v].pass = true;
for (int w = 0; w < G.vexnum; w++)
{
if (G.cities[w].pass == false && mincost + a[v][w] < dist[depart][w])
{
dist[depart][w] = mincost + a[v][w];
//拼接
from[w] = v;
}
}
}
//output
int num = dest;
cout << G.cities[num].city << "<--";
while (num != depart)
{
cout << G.cities[from[num]].city << "<--";
num = from[num];
}
cout << endl;
cout << dist[depart][dest] << endl;
}
int main()
{
ALGraph G;
Create (G) ;
DFS(&G, 0);
float (*b)[MAX];//指向数组的指针
b = new float[MAX][MAX];
Dijkstra(G, b);
delete[] b;
return 0;
}
QwQ如果大佬们有更好的做法希望指导啊~