Linklist.h
#ifndef LINKLIST_H_INCLUDED
#define LINKLIST_H_INCLUDED
/***********************************
版权所有: 2017,hudejie
文件名称: 单链表头文件
内容摘要: 该文件用于描述单链表的结构体及函数定义
当前版本: V1.0
作者: hudejie
完成日期: 2017.12.21
***********************************/
#include "stdio.h"
#include "malloc.h"
using namespace std;
typedef struct L
{
int num; //地点编号
char name[62]; //地点名称
char rem[60]; //地点信息
} ElemType;
//typedef int ElemType;
typedef struct LNode
{
ElemType data;
struct LNode *next;
}LinkList;
void CreateListF(LinkList *&L,ElemType a);//头插法(链表,自定义的数据类型)
//void CreateListR(LinkList *&L,ElemType a[],int n); //尾插法建立单链表
void DestroyList(LinkList *&L); //销毁单链表 (链表)
void DispList(LinkList *L); //输出单链表所有地点信息(链表)
void InitList(LinkList *&L); //初始化线性表(链表)
bool LinkEmpt(LinkList *&L); //判断链表是否为空(链表)
//int Lisklength(LinkList *&L); //求链表长度
//bool GetElem(LinkList *&L,int i,ElemType &e); //求指定位置的数据元素
int LocateElem(LinkList *L,ElemType e); //按元素值查找(链表,自定义的数据类型)
bool ListInsert(LinkList *&L,int i,ElemType e); //插入元素(链表,插入位置,自定义的数据类型)
bool Delete(LinkList *&L,int i,ElemType &e); //删除元素(链表,删除位置,自定义的数据类型)
#endif // LINKLIST_H_INCLUDED
Linklist.cpp
/***********************************
版权所有: 2017,hudejie
文件名称: 单链表头文件
内容摘要: 该文件用于描述单链表各种函数的实现
当前版本: V1.4
作者: hudejie
完成日期: 2017.12.21
***********************************/
#include "linklist.h"
/***********************************
功能描述:头插法建立链表
输入参数:链表头指针,自定义数据
输出参数:无
返回值:链表头指针
***********************************/
void CreateListF(LinkList *&L,ElemType a)//
{
LinkList *s;
s=(LinkList *)malloc(sizeof(LinkList));
s->data=a;
s->next=L->next;
L->next=s;
}
/***********************************
功能描述:销毁单链表
输入参数:链表头指针
输出参数:无
返回值:链表头指针
***********************************/
void DestroyList(LinkList *&L) //
{
LinkList *p=L,*q=p->next;
while(q!=NULL)
{
free(p); //释放
p=q;
q=q->next;
}
free(p);
}
/***********************************
功能描述:输出单链表所有地点信息
输入参数:链表头指针
输出参数:链表内地点信息
返回值:链表头指针
***********************************/
void DispList(LinkList *L) //
{
LinkList *p=L->next;
printf("所有地点信息如下:\n\n");
printf("地点编号:\t地点名称:\t\t地点信息:\n");
while (p!=NULL)
{
printf(" %d\t\t %s \t\t %s\n",p->data.num,p->data.name,p->data.rem); //输出链表信息
p=p->next;
}
printf("\n");
}
/***********************************
功能描述:初始化单链表
输入参数:链表头指针
输出参数:无
返回值:链表头指针
***********************************/
void InitList(LinkList *&L) //初始化线性表
{
L=(LinkList *)malloc(sizeof(LinkList));
L->next=NULL;
}
bool Delete(LinkList *&L,int i,ElemType &e) //删除元素
{
int j=0;
LinkList *p=L,*q;
while(j<i-1&&p!=NULL)
{
j++;
p=p->next;
}
if(p==NULL)
return false;
else
{
q=p->next;
if(q==NULL)
return false;
e=q->data;
p->next=q->next;
free(q);
return true;
}
}
/***********************************
功能描述:单链表插入元素
输入参数:链表头指针,插入位置,自定义数据类型
输出参数:无
返回值:链表头指针
***********************************/
bool ListInsert(LinkList *&L,int i,ElemType e) //插入元素
{
int j=0;
LinkList*p=L,*s;
while(p!=NULL && j<i-1)
{
j++;
p=p->next;
}
if(p==NULL)
return false;
else
{
s=(LinkList *)malloc(sizeof(LinkList));
s->data=e;
s->next=p->next;
p->next=s;
return true;
}
}
graph.h
#ifndef GRAPH_H_INCLUDED
#define GRAPH_H_INCLUDED
/***********************************
版权所有: 2017,hudejie
文件名称: 图头文件
内容摘要: 该文件用于描述图的结构体及函数定义
当前版本: V1.1
作者: hudejie
完成日期: 2017.12.21
***********************************/
#include"linklist.h"
#define MAXV 100 //最大顶点个数
#define INF 32767 //INF表示∞
typedef int InfoType;
//以下定义邻接矩阵类型
typedef struct
{
int no; //顶点编号
InfoType info; //顶点其他信息,在此存放带权图权值
} VertexType; //顶点类型
typedef struct //图的定义
{
int edges[MAXV][MAXV]; //邻接矩阵
int n,e; //顶点数,弧数
VertexType vexs[MAXV]; //存放顶点信息
}MGraph;
void ArrayToMat(int *Arr, int n, MGraph &g); //用普通数组构造图的邻接矩阵(数组,定点个数,邻接矩阵)
//Dijkstra算法,复杂度为O(n^3);用于寻找图中指定节点到其余各节点的最短路径
void Dijkstra(MGraph g,int v,LinkList *a,int p); //最短路径算法 (邻接矩阵,起始顶点,链表,尾顶点)
void Dispath(MGraph g,int dist[],int path[],int S[],int i);//输出单源最短路径(邻接矩阵,距离数组,路径数组,数组,尾顶点)
#endif // GRAPH_H_INCLUDED
graph.cpp
/***********************************
版权所有: 2017,hudejie
文件名称: 图文件
内容摘要: 该文件用于描述图各种函数的实现
当前版本: V1.5
作者: hudejie
完成日期: 2017.12.21
***********************************/
#include <stdio.h>
#include <malloc.h>
#include "graph.h"
/***********************************
功能描述:二维数组转置邻接矩阵
输入参数:整形指针,顶点个数,邻接矩阵
输出参数:无
返回值:邻接矩阵
***********************************/
void ArrayToMat(int *Arr, int n, MGraph &g) //二维数组转置邻接矩阵(数组,顶点数,邻接矩阵)
{
int i,j,count=0; //count用于统计边数,即矩阵中非0元素个数
g.n=n; //顶点数
for (i=0; i<g.n; i++)
for (j=0; j<g.n; j++)
{
g.edges[i][j]=Arr[i*n+j]; //将Arr看作n×n的二维数组,Arr[i*n+j]即是Arr[i][j],计算存储位置的功夫在此应用
if(g.edges[i][j]!=0 && g.edges[i][j]!=INF) //寻找顶点
count++;
}
g.e=count;
}
/***********************************
功能描述:二维数组转置邻接矩阵
输入参数:邻接矩阵,距离,路径,整形数组,排序顶点,链表,排序尾点
输出参数:输出最短路径
返回值:无
***********************************/
void Dispath(MGraph g,int dist[],int path[],int S[],int v,LinkList *a,int i) //输出单源最短路径(邻接矩阵,)
{
LinkList *b,*c;
int j,k;
int apath[MAXV],d; //逆向存放一条顶点路径及其定点个数
//循环输出顶点v到i的路径
if(S[i]==1&&i!=v)
{
b=a;
c=a;
while(b->next!=NULL) //寻找链表中与顶点编号相同的顶点名称
{
b=b->next;
if(b->data.num==v)
break;
}
while(c->next!=NULL) //寻找链表中与顶点编号相同的顶点名称
{
c=c->next;
if(c->data.num==i)
break;
}
printf("从 %s 到 %s 的最短路径为:",b->data.name,c->data.name);
d=0;
apath[d]=i; //添加路径的终点
k=path[i];
if(k==-1) //没有路径的情况
printf("无路径\n");
else //存在路径时输出路径
{
while(k!=v)
{
d++;
apath[d]=k;
k=path[k];
}
d++; //添加路径上的起点
apath[d]=v;
b=a;
while(b->next!=NULL)
{
b=b->next;
if(b->data.num==apath[d])
break;
}
printf("%s",b->data.name); //先输出起点
for(j=d-1; j>=0; j--) //在输出其他顶点
{
b=a;
while(b->next!=NULL) //寻找链表中与顶点编号相同的顶点名称
{
b=b->next;
if(b->data.num==apath[j])
break;
}
printf("->%s",b->data.name);
}
printf(" \t路径长度为:%d千米",dist[i]);
printf("\n\n");
}
}
}
/***********************************
功能描述:Dijkstra算法,复杂度为O(n^3);用于寻找图中指定节点到其余各节点的最短路径
输入参数:邻接矩阵,排序顶点,链表,排序尾点
输出参数:无
返回值:邻接矩阵
***********************************/
void Dijkstra(MGraph g,int v,LinkList *a,int p)
{
int dist[MAXV],path[MAXV]; //用于记录距离和路径
int s[MAXV]; //用于加入节点
int mindis,i,j,u;
for (i=0; i<g.n; i++)
{
dist[i]=g.edges[v][i]; //距离初始化
s[i]=0; //s[]置空
if (g.edges[v][i]<INF) //路径初始化
path[i]=v;
else
path[i]=-1;
}
s[v]=1;
path[v]=0; //源点编号v放入s中
for (i=0; i<g.n; i++) //循环直到所有顶点的最短路径都求出
{
mindis=INF; //mindis置最小长度初值
for (j=0; j<g.n; j++) //选取不在s中且具有最小距离的顶点u
if (s[j]==0 && dist[j]<mindis)
{
u=j;
mindis=dist[j];
}
s[u]=1; //顶点u加入s中
for (j=0; j<g.n; j++) //修改不在s中的顶点的距离
if (s[j]==0)
if (g.edges[u][j]<INF && dist[u]+g.edges[u][j]<dist[j]) //寻找路径中较短的呢个
{
dist[j]=dist[u]+g.edges[u][j];
path[j]=u;
}
}
Dispath(g,dist,path,s,v,a,p); //输出最短路径
}
operate.h
#ifndef OPERATE_H_INCLUDED
#define OPERATE_H_INCLUDED
/***********************************
版权所有: 2017,hudejie
文件名称: 功能实现操作头文件
内容摘要: 该文件用于将各文件链接在一起实现主函数的应用
当前版本: V1.2
作者: hudejie
完成日期: 2017.12.21
***********************************/
#include"stdio.h"
#include"graph.h"
#include"linklist.h"
using namespace std;
void Read(LinkList *&b); //读操作 (链表)
void Write(LinkList *&b); //写操作(链表)
void entermain(MGraph g,LinkList *b); //初始页面(邻接矩阵,链表)
void enter1(MGraph g,LinkList *b); //火警响应页面(邻接矩阵,链表)
void enter2(MGraph g,LinkList *b); //火警响应页面(邻接矩阵,链表)
void Map(); //平面图
#endif // OPERATE_H_INCLUDED
//LinkList *&b,
operate.cpp
/***********************************
版权所有: 2017,hudejie
文件名称: 功能实现操作文件
内容摘要: 该文件用于将各文件链接在一起实现主函数的应用
当前版本: V1.3
作者: hudejie
完成日期: 2017.12.21
***********************************/
#include"stdio.h"
#include"iostream"
#include <cstdlib>
#include "operate.h"
#include <fstream>
#include"string"
#include"graph.h"
#include"cstring"
using namespace std;
char a[10];
/***********************************
功能描述:用于读取文件信息
输入参数:链表
输出参数:无
返回值:链表
***********************************/
void Read(LinkList *&b) //读操作
{
LinkList *a,*c;
c=b;
ifstream file("地图信息.txt",ios::in);
a=(LinkList *)malloc(sizeof(LinkList));
while (file)
{
file>>a->data.num>>a->data.name>>a->data.rem; //讲信息读入链表中
if (!file) break; //如果File为空 跳出While循环,也就是说文件的数据读完了就不在增加equipment数组
//if(file.eof()) break;
c->next=a;
c=a;
a=(LinkList *)malloc(sizeof(LinkList));
}
c->next=NULL;
file.close();
}
/***********************************
功能描述:将链表信息读到文件里
输入参数:链表
输出参数:无
返回值:链表
***********************************/
void Write(LinkList *&b) //写操作
{
LinkList *a;
a=b->next;
ofstream file("地图信息.txt",ios::out); //ios::out 以输出方式打开文件,有过已有此名字的文件,则将其原有内容全部清除
file<<"地点编号\t\t"<<"地点名称\t\t"<<"地点简介\n";
while(a!=NULL)
{
file<<a->data.num<<" \t\t"<<a->data.name<<" \t\t"<<a->data.rem<<"\n"; //将地图信息写入硬盘
a=a->next;
}
file.close();
}
/***********************************
功能描述:火警与医疗系统界面
输入参数:链表,邻接矩阵
输出参数:界面
返回值:无
***********************************/
void entermain(MGraph g,LinkList *b) //初始页面
{
int tmp;
system("cls");
printf("-----------------------欢迎登录烟台大学火警与医疗系统-----------------------\n\n\n");
printf(" 1.火警响应\n");
printf(" 2.医疗救助\n");
printf(" 3.地点信息查看\n");
printf(" 4.地图查看\n");
printf(" 5.退出\n");
cout<<"请按提示输入数字:";
cin>>tmp;
while (cin.fail()) //清除输入的非数字字符
{
cin.clear();
cin>>a;
cout << "输入的不是数字,请输入一个数:";
cin >> tmp;
}
while(1) //判断输入的数字是否正确
{
if(tmp>=1&&tmp<=5)
break;
else
{
cout<<"输入错误,请重新输入:";
cin>>tmp;
while (cin.fail())
{
cin.clear();
cin>>a;
cout << "输入的不是数字,请输入一个数:";
cin >> tmp;
}
}
}
switch(tmp)
{
case 1:
enter1(g,b); //火警响应系统页面
break;
case 2:
enter2(g,b); //医疗救助系统页面
break;
case 3:
DispList(b);
system("pause");
entermain(g,b); //初始页面
break;
case 4:
Map();
system("pause");
entermain(g,b); //初始页面
case 5:
return;
break;
}
}
/***********************************
功能描述:火警响应系统界面
输入参数:链表,邻接矩阵
输出参数:界面
返回值:无
***********************************/
void enter1(MGraph g,LinkList *b) //火警响应页面
{
int tmp;
system("cls");
printf("-----------------------------火警响应系统-------------------------------\n\n\n");
printf(" 1.校医院\n");
printf(" 2.宿舍楼\n");
printf(" 3.钟楼\n");
printf(" 4.千米长廊\n");
printf(" 5.新图\n");
printf(" 6.综合楼\n");
printf(" 7.七餐\n");
printf(" 8.返回\n");
printf("请选择报警地点:");
cin>>tmp;
while (cin.fail()) //清除输入的非数字字符
{
cin.clear();
cin>>a;
cout << "输入的不是数字,请输入一个数:";
cin >> tmp;
}
while(1) //判断输入是否正确
{
if(tmp>=1&&tmp<=8)
break;
else
{
cout<<"输入错误,请重新输入";
cin>>tmp;
while (cin.fail())
{
cin.clear();
cin>>a;
cout << "输入的不是数字,请输入一个数:";
cin >> tmp;
}
}
}
if(tmp!=8)
{
Dijkstra(g,0,b,tmp);
Map(); //地图
system("pause");
entermain(g,b); //初始页面
}
else
entermain(g,b); //初始页面
}
/***********************************
功能描述:医疗救助系统统界面
输入参数:链表,邻接矩阵
输出参数:界面
返回值:无
***********************************/
void enter2(MGraph g,LinkList *b) //火警响应页面
{
int tmp;
system("cls");
printf("-----------------------------医疗救助系统-------------------------------\n\n\n");
printf(" 1.警卫处\n");
printf(" 2.宿舍楼\n");
printf(" 3.钟楼\n");
printf(" 4.千米长廊\n");
printf(" 5.新图\n");
printf(" 6.综合楼\n");
printf(" 7.七餐\n");
printf(" 8.返回\n");
printf("请选择医疗地点:");
cin>>tmp;
while (cin.fail()) //清除输入的非数字字符
{
cin.clear();
cin>>a;
cout << "输入的不是数字,请输入一个数:";
cin >> tmp;
}
while(1) //判断输入是否正确
{
if(tmp>=1&&tmp<=8)
break;
else
{
cout<<"输入错误,请重新输入";
cin>>tmp;
while (cin.fail())
{
cin.clear();
cin>>a;
cout << "输入的不是数字,请输入一个数:";
cin >> tmp;
}
}
}
switch(tmp)
{
case 1:
Dijkstra(g,1,b,0);
Map(); //地图
system("pause");
entermain(g,b); //初始页面
break;
case 2:
case 3:case 4:case 5:case 6:case 7:
Dijkstra(g,1,b,tmp);
Map(); //地图
system("pause");
entermain(g,b); //初始页面
break;
case 8:
entermain(g,b); //初始页面
break;
}
}
/***********************************
功能描述:地图界面
输入参数:无
输出参数:界面
返回值:无
***********************************/
void Map() //平面图
{
printf("\n");
printf(" 校医院--------------------- 宿舍楼 --------------------------火警点 \n");
printf(" | \\ || // | \n");
printf(" | \\ || // | \n");
printf(" | \\ || // | \n");
printf(" | \\ \\ // | \n");
printf(" | \\ \\ // | \n");
printf(" | \\ \\ // | \n");
printf(" | ----------------------- 钟楼----------------- | \n");
printf(" | // | \\ | \n");
printf(" | // | \\ | \n");
printf(" 千 // | \\ | \n");
printf(" 米 // | \\| \n");
printf(" 长---- | 七餐 \n");
printf(" 廊 | | \n");
printf(" | | | \n");
printf(" | | | \n");
printf(" | | | \n");
printf(" |------------ 图书馆 ------------ 综合楼 ------------------------- \n");
}
main.cpp
/***********************************
版权所有: 2017,hudejie
文件名称: 主函数
内容摘要: 用于程序的初始化以及负责程序的运行
当前版本: V1.5
作者: hudejie
完成日期: 2017.12.21
***********************************/
#include "linklist.h"
#include"iostream"
#include"graph.h"
#include "operate.h"
#include"string"
#include"cstring"
using namespace std;
/***********************************
功能描述:用于程序的初始化以及负责程序的运行
输入参数:无
输出参数:函数
返回值:0
***********************************/
int main()
{
int tmp;
MGraph g;
LinkList *L;
InitList(L);
LinkList *a,*c;
c=L;
a=(LinkList *)malloc(sizeof(LinkList));
a->data.num=0;
strcpy(a->data.name,"火警点");
strcpy(a->data.rem,"校园戒备中心,二十四小时不间断值班");
c->next=a;
c=a;
a=(LinkList *)malloc(sizeof(LinkList));
a->data.num=1;
strcpy(a->data.name,"校医院");
strcpy(a->data.rem,"一家小型医院,服务全校师生");
c->next=a;
c=a;
a=(LinkList *)malloc(sizeof(LinkList));
a->data.num=2;
strcpy(a->data.name,"宿舍楼");
strcpy(a->data.rem,"学生栖息的小屋,同学们最喜欢的地方");
c->next=a;
c=a;
a=(LinkList *)malloc(sizeof(LinkList));
a->data.num=3;
strcpy(a->data.name,"钟楼");
strcpy(a->data.rem,"烟大的标志性建筑,计控学院的根据地");
c->next=a;
c=a;
a=(LinkList *)malloc(sizeof(LinkList));
a->data.num=4;
strcpy(a->data.name,"千米长廊");
strcpy(a->data.rem,"据说一千米,但感觉只有九百九十九米");
c->next=a;
c=a;a=(LinkList *)malloc(sizeof(LinkList));
a->data.num=5;
strcpy(a->data.name,"新图");
strcpy(a->data.rem,"学霸们经常去的地方");
c->next=a;
c=a;
a=(LinkList *)malloc(sizeof(LinkList));
a->data.num=6;
strcpy(a->data.name,"综合楼");
strcpy(a->data.rem,"配备有各种大中小型自习教室");
c->next=a;
c=a;
a=(LinkList *)malloc(sizeof(LinkList));
a->data.num=7;
strcpy(a->data.name,"七餐");
strcpy(a->data.rem,"上世纪全亚洲最大的餐厅");
c->next=a;
c=a;
c->next=NULL;
int A[8][8]=
{
{0,INF,3,4,INF,INF,INF,7},
{INF,0,2,4,11,INF,INF,INF},
{3,2,0,7,INF,INF,INF,INF},
{4,4,7,0,5,INF,6,8},
{INF,11,INF,5,0,2,INF,INF},
{12,INF,INF,INF,2,0,1,INF},
{INF,INF,INF,6,INF,1,0,5},
{7,INF,INF,INF,INF,INF,5,0}
};
ArrayToMat(A[0],8,g);
//Dijkstra(g,0,L);
Write(L);
entermain(g,L); //初始页面
return 0;
}
课程设计总结:
因为我的程序可以看成是一个求最短路径的问题,所以要用到图中最短路径的算法(其实已经啥都不会了),在考虑用什么算法就把两个算法的视频又看了一遍,看完后才对这个项目有信心。数据结构上了一个学期了,每个模块差不多都忘记了,课程设计的过程中也是一边做一遍学,这个系统花时间最多的不是图,也不是链表而是文件,整整花了两天时间调试文件,调试出来一看二十行代码不到,最后还没怎么用,想想前两天真的伤心啊!!!
短暂的课程设计就这样过去了,感谢那个帮我调了两个小时代码的哥们,感谢给我指导,给我帮助,给我意见的老师,也感谢陪我一起打代码的同学们。