学习了一学期的数据结构的课设报告,这里主要发出我的代码及帮助读者理解的部分实验报告,写的不好之处还望提出改进继续优化。
后面直接一次性给出了完整代码,方便各位读者直接分享使用、方便移植。
也没有给代码添加过多的详细注释,因为像这种完全用面向过程的c语言写出的东西各部分之间的调用关系也不是很深,只有个别的算法可能需要好好研究一番。
目录
一、所用知识
(1)必掌握
- C语言
- 链表
- 递归
- 图
(2)算法
- DFS(深度优先搜索)
- 链表的初始化、添加删除结点、清空、遍历、复制链表
- 迪杰斯特拉算法
- 构造邻接矩阵
二、实现功能
三、程序结构
四、main函数流程
五、数据存储结构设计
(1)图结构
typedef enum{DG,DN,UDG,UDN}GraphKind;//要定义图的类型选择
typedef struct ArcNode
{
int adj; //图的权值
char * info; //顶点的相关信息,不过此程序中并未使用此处的定义
}ArcNode;
typedef struct
{
int xi; //图的顶点在数组中的下标的记录
char vi; //图的顶点的代号
char ki[500]; //顶点的相关信息描述
}VertexType;
typedef struct {
VertexType vertex[MAX_VERtEX_NUM];
//存放顶点的数组
ArcNode arcs[MAX_VERtEX_NUM][MAX_VERtEX_NUM];
//图的邻接矩阵
int vexnum,arcnum;
//顶点和边的定义
GraphKind kind;
//图的种类,此程序中创建的时无向有权网(UDN)
}AdjMatrix;
(2)链表结构
typedef struct Node
{
char data; //结点的相关信息(存储的A、B、C···)
struct Node *next; //next指针域
}Node,*LinkList; //Node用于sizeof探测空间大小
//LinkList用于定义指针类型
六、完整代码
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define MAX_VERtEX_NUM 20
#define INFINITY 32786
#define Error -1;
#define True 1
#define False 0
int visited[MAX_VERtEX_NUM];
int stack[MAX_VERtEX_NUM];
int end,top=0,start=0;
//图结构
typedef enum{DG,DN,UDG,UDN}GraphKind;
typedef struct ArcNode
{
int adj;
char * info;
}ArcNode;
typedef struct
{
int xi;
char vi;
char ki[500];
}VertexType;
typedef struct {
VertexType vertex[MAX_VERtEX_NUM];
ArcNode arcs[MAX_VERtEX_NUM][MAX_VERtEX_NUM];
int vexnum,arcnum;
GraphKind kind;
}AdjMatrix;
//链表结构
typedef struct Node
{
char data;
struct Node *next;
}Node,*LinkList;
LinkList Path[MAX_VERtEX_NUM];
int Dist[MAX_VERtEX_NUM];
void Init_List(LinkList *L)//初始化链表
{
*L=(LinkList)malloc(sizeof(Node));//创建头节点
(*L)->next=NULL;
}
void AddTail(LinkList *L,char i)//尾插法加结点
{
Node *p,*q;
q=(*L);
while(q->next!=NULL){
q=q->next;
}
p=(LinkList)malloc(sizeof(Node));
if(p){
p->data=i;
p->next=NULL;
q->next=p;
}
}
int Member(char ver,LinkList s) //判断ver是否在链表s中
{
Node *temp;
temp=s->next;
while(temp!=NULL){
if(temp->data==ver)
return True;
temp=temp->next;
}
return False;
}
void Clear_Link(LinkList *L)//清空链表
{
Node *temp,*del;
temp=(*L);
while(temp->next!=NULL){
del=temp->next;
temp->next=del->next;
free(del);
}
}
void CopyPath(LinkList *T,LinkList *S) //把s复制到t中
{
Node *s,*t,*add;
t=(*T);
s=(*S)->next;
Clear_Link(T);
while(s!=NULL){
add=(LinkList)malloc(sizeof(Node));
if(add){
add->data=s->data;
add->next=t->next;
t->next=add;
s=s->next;
t=t->next;
}
}
}
void ShortestPath_DIJ(AdjMatrix G,int v0)
{
int i,k,t,min;
LinkList s;//最小路径集
for(i=0;i<G.vexnum;i++)
{
Init_List(&Path[i]);//初始化最初路径
Dist[i]=G.arcs[v0][i].adj;
if(Dist[i]<INFINITY)//如果有路径,加入
{
AddTail(&Path[i],G.vertex[v0].vi);
AddTail(&Path[i],G.vertex[i].vi);
}
}
Init_List(&s);//初始化S集
AddTail(&s,G.vertex[v0].vi);//将起始点加入S集
for(t=1;t<G.vexnum;t++)//循环M->vertexnum-1次
{
min=INFINITY;
for(i=0;i<G.vexnum;i++){
if(!Member(G.vertex[i].vi,s)&&Dist[i]<min){//节点i不在S集并且起始点到i的路径长度小于S集中最小值
k=i;
min=Dist[i];
}
}
if(min==INFINITY) return;
AddTail(&s,G.vertex[k].vi);
for(i=0;i<G.vexnum;i++){
if(!Member(G.vertex[i].vi,s)&&G.arcs[k][i].adj!=INFINITY&&(Dist[k]+G.arcs[k][i].adj<Dist[i])){
Dist[i]=Dist[k]+G.arcs[k][i].adj;
CopyPath(&Path[i],&Path[k]);
//Path[i]=Path[k];
AddTail(&Path[i],G.vertex[i].vi);
}
}
}
}
void print_minpath(LinkList L)//打印全部最小路径
{
Node *temp,*p;
p=L->next;
temp=p->next;
printf(" %c",p->data);
while(temp!=NULL){
printf("->%c",temp->data);
temp=temp->next;
}
printf("\n");
}
void print_minpath2(LinkList L)//打印单条最小路径
{
Node *temp,*p;
p=L->next;
temp=p->next;
printf("%c",p->data);
while(temp!=NULL){
printf("->%c",temp->data);
temp=temp->next;
}
printf("\n");
}
void print_MinPaths(AdjMatrix *G,char v0) //遍历Path
{
for(int i=0;i<G->vexnum;i++){
if(i!=v0){
print_minpath(Path[i]);
}
}
}
void Print_Dist(int dist[],int v0,int vex_num)//打印距离
{
int i;
for(i=0;i<vex_num;i++){
printf("*");
if(i!=v0){
if(Dist[i]==INFINITY){
printf("%d ",-1);
}else{
printf("%d ",Dist[i]);
}
}
}
}
int LocateVertex(AdjMatrix *G,char v)//搜索该顶点在数组中的位置
{
int j=Error;
for(int k=0;k<G->vexnum;k++)
if(G->vertex[k].vi==v)
{j=k;break;}
return(j);
}
void CreateUDN(AdjMatrix *G){ //构造无向有权网
G->vexnum=10,G->arcnum=18;
G->vertex[0].vi='A';
G->vertex[0].xi=0;
strcpy(G->vertex[0].ki,"校门:建于1912年,是学校的重要标志,一般可控制人员和车辆出入");
G->vertex[1].vi='B';
G->vertex[1].xi=1;
strcpy(G->vertex[1].ki,"教学楼:教学楼就是学校教学区的主体建筑。教学区一般采取以教学楼为主体的布局。教学楼一般分为教学单元、实验单元和办公单元等。");
G->vertex[2].vi='C';
G->vertex[2].xi=2;
strcpy(G->vertex[2].ki,"人文楼:人文学科的综合功能大楼。即文学、哲学、国学、历史 艺术、美学、教育、社会等学科,包括教学、科研、办公、会议、图书阅览等综合功能大楼。");
G->vertex[3].vi='D';
G->vertex[3].xi=3;
strcpy(G->vertex[3].ki,"图书馆:是搜集、整理、收藏图书资料以供人阅览、参考的机构");
G->vertex[4].vi='E';
G->vertex[4].xi=4;
strcpy(G->vertex[4].ki,"大学生活动中心:是大学设立的组织指导大学生进行文化艺术娱乐活动,丰富大学生课余生活的场所。");
G->vertex[5].vi='F';
G->vertex[5].xi=5;
strcpy(G->vertex[5].ki,"学生公寓:是学生日常生活与学习的重要场所,是课堂之外对学生进行政治思想工作和素质教育的重要阵地。");
G->vertex[6].vi='G';
G->vertex[6].xi=6;
strcpy(G->vertex[6].ki,"操场:建有标准的8跑道塑胶运动场,可供学生进行体育比赛以及娱乐活动");
G->vertex[7].vi='H';
G->vertex[7].xi=7;
strcpy(G->vertex[7].ki,"食堂:学校食堂比较规范,相对企业食堂还是比较讲究菜色和卫生服务的,一般都经过单位监督和经营认证。");
G->vertex[8].vi='I';
G->vertex[8].xi=8;
strcpy(G->vertex[8].ki,"菜鸟驿站:是一个由菜鸟网络牵头建立面向社区和校园的物流服务平台网络平台,作为菜鸟网络五大战略方向之一为网购用户提供包裹代收服务,");
G->vertex[9].vi='J';
G->vertex[9].xi=9;
strcpy(G->vertex[9].ki,"田径运动场:是一类开展体育运动场地。有若干条跑道,中央有可供设计球类运动场地,两侧和两端有可供修建沙坑和一些投掷区的空底。");
for(int i=0;i<G->vexnum;i++){
for(int j=0;j<G->vexnum;j++){
G->arcs[i][j].adj=INFINITY;
G->arcs[i][j].info=NULL;
}
}
char v1,v2;int i,j,w;
i=LocateVertex(G,'A');
j=LocateVertex(G,'B');
w=150;
G->arcs[i][j].adj=w;
G->arcs[j][i].adj=w;
i=LocateVertex(G,'A');
j=LocateVertex(G,'C');
w=200;
G->arcs[i][j].adj=w;
G->arcs[j][i].adj=w;
i=LocateVertex(G,'A');
j=LocateVertex(G,'D');
w=400;
G->arcs[i][j].adj=w;
G->arcs[j][i].adj=w;
i=LocateVertex(G,'A');
j=LocateVertex(G,'E');
w=600;
G->arcs[i][j].adj=w;
G->arcs[j][i].adj=w;
i=LocateVertex(G,'B');
j=LocateVertex(G,'D');
w=150;
G->arcs[i][j].adj=w;
G->arcs[j][i].adj=w;
i=LocateVertex(G,'B');
j=LocateVertex(G,'C');
w=300;
G->arcs[i][j].adj=w;
G->arcs[j][i].adj=w;
i=LocateVertex(G,'C');
j=LocateVertex(G,'D');
w=210;
G->arcs[i][j].adj=w;
G->arcs[j][i].adj=w;
i=LocateVertex(G,'C');
j=LocateVertex(G,'F');
w=300;
G->arcs[i][j].adj=w;
G->arcs[j][i].adj=w;
i=LocateVertex(G,'D');
j=LocateVertex(G,'E');
w=120;
G->arcs[i][j].adj=w;
G->arcs[j][i].adj=w;
i=LocateVertex(G,'D');
j=LocateVertex(G,'F');
w=250;
G->arcs[i][j].adj=w;
G->arcs[j][i].adj=w;
i=LocateVertex(G,'E');
j=LocateVertex(G,'G');
w=100;
G->arcs[i][j].adj=w;
G->arcs[j][i].adj=w;
i=LocateVertex(G,'F');
j=LocateVertex(G,'G');
w=350;
G->arcs[i][j].adj=w;
G->arcs[j][i].adj=w;
i=LocateVertex(G,'F');
j=LocateVertex(G,'I');
w=250;
G->arcs[i][j].adj=w;
G->arcs[j][i].adj=w;
i=LocateVertex(G,'F');
j=LocateVertex(G,'J');
w=150;
G->arcs[i][j].adj=w;
G->arcs[j][i].adj=w;
i=LocateVertex(G,'G');
j=LocateVertex(G,'H');
w=50;
G->arcs[i][j].adj=w;
G->arcs[j][i].adj=w;
i=LocateVertex(G,'G');
j=LocateVertex(G,'I');
w=200;
G->arcs[i][j].adj=w;
G->arcs[j][i].adj=w;
i=LocateVertex(G,'H');
j=LocateVertex(G,'I');
w=30;
G->arcs[i][j].adj=w;
G->arcs[j][i].adj=w;
i=LocateVertex(G,'I');
j=LocateVertex(G,'J');
w=200;
G->arcs[i][j].adj=w;
G->arcs[j][i].adj=w;
}
void PrintGrapth(AdjMatrix G) //输出邻接矩阵
{
for (int i=0;i<G.vexnum;i++){
for (int j=0;j<G.vexnum;j++){
printf("%d\t",G.arcs[i][j].adj);
}
printf("\n");
}
}
void DFS(AdjMatrix G,int v0)
{
printf("%c ",G.vertex[v0].vi);
visited[v0]=True;
for(int vj=0;vj<G.vexnum;vj++)
if(!visited[vj]&&G.arcs[v0][vj].adj!=0)
DFS(G,vj);
}
void DFS_(AdjMatrix G,int v0,int v)
{
if(v0==end){
printf("%c",G.vertex[v].vi);
for(int i=0;i<top;i++){
printf("->%c",G.vertex[stack[i]].vi);
}
printf("\n");
return;
}
visited[v]=True;
for(int vj=0;vj<G.vexnum;vj++){
if(!visited[vj]&&G.arcs[v0][vj].adj!=0&&G.arcs[v0][vj].adj<INFINITY){
visited[vj]=True;
stack[top]=G.vertex[vj].xi;
top++;
DFS_(G,G.vertex[vj].xi,v);
visited[vj]=False;
top--;
}
}
}
void fun1(AdjMatrix G)
{
printf("\n(A)校门[0]~(B)教学楼[1]~(C)人文楼[2]~(D)图书馆[3]~(E)大学生活动中心[4]~(F)学生公寓[5]~(G)操场[6]~(H)食堂[7]~(I)菜鸟驿站[8]~(J)田径场[9]\n");
printf("\n起始景点位置[输入数字代号]:");
scanf("%d",&start);
printf("\n目标景点位置[输入数字代号]:");
scanf("%d",&end);
printf("\n最佳路径是:");
ShortestPath_DIJ(G,start);
print_minpath2(Path[end]);
printf("\n距离是:");
//Print_Dist(Dist,start,G.vexnum);
printf("%dm\n",Dist[end]);
}
void fun2(AdjMatrix G)
{
printf("\n(A)校门[0]~(B)教学楼[1]~(C)人文楼[2]~(D)图书馆[3]~(E)大学生活动中心[4]~(F)学生公寓[5]~(G)操场[6]~(H)食堂[7]~(I)菜鸟驿站[8]~(J)田径场[9]\n");
printf("\n起始景点位置:");
scanf("%d",&start);
printf("\n从当前景点到达任意景点最佳路径如下:\n\n");
ShortestPath_DIJ(G,start);
print_MinPaths(&G,start);
}
void fun3(AdjMatrix G)
{
printf("\n(A)校门[0]~(B)教学楼[1]~(C)人文楼[2]~(D)图书馆[3]~(E)大学生活动中心[4]~(F)学生公寓[5]~(G)操场[6]~(H)食堂[7]~(I)菜鸟驿站[8]~(J)田径场[9]\n");
printf("\n起始景点位置[输入数字代号]:");
scanf("%d",&start);
printf("\n目标景点位置[输入数字代号]:");
scanf("%d",&end);
printf("\n\n所有路径如下:\n\n");
DFS_(G,start,start);
}
void fun4(AdjMatrix G)
{
printf("\n");
for(int i=0;i<G.vexnum;i++){
printf("%c ",G.vertex[i].vi);
printf("%s",G.vertex[i].ki);
printf("\n");
}
}
void fun5(AdjMatrix G)
{
int i;
printf("\n(A)校门[0]~(B)教学楼[1]~(C)人文楼[2]~(D)图书馆[3]~(E)大学生活动中心[4]~(F)学生公寓[5]~(G)操场[6]~(H)食堂[7]~(I)菜鸟驿站[8]~(J)田径场[9]\n");
printf("\n输入要查询的景点[输入数字代号]:");
scanf("%d",&i);
printf("\n");
printf("%c ",G.vertex[i].vi);
printf("%s",G.vertex[i].ki);
printf("\n");
}
void fun6(AdjMatrix G)
{
printf("\n");
PrintGrapth(G);
}
void fun7(AdjMatrix G)
{
printf("\n");
DFS(G,0);
printf("\n");
}
int main()
{
int i;
AdjMatrix G;
CreateUDN(&G);
memset(visited,False,sizeof(visited));
putchar('\n');
system("clear"); //Windows下换成system("cls")
printf("****************************导航系统****************************\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("****************************导航系统****************************\n");
printf("\n*****选择操作:");
scanf("%d",&i);
while(True){
system("clear"); //Windows下换成system("cls")
printf("****************************导航系统****************************\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("****************************导航系统****************************\n");
switch (i)
{
case 1:
fun1(G);
memset(Path,0,sizeof(Path));
memset(Dist,0,sizeof(Dist));
printf("\n*****选择操作:");
scanf("%d",&i);
break;
case 2:
fun2(G);
memset(Path,0,sizeof(Path));
memset(Dist,0,sizeof(Dist));
printf("\n*****选择操作:");
scanf("%d",&i);
break;
case 3:
fun3(G);
printf("\n*****选择操作:");
scanf("%d",&i);
break;
case 4:
fun4(G);
printf("\n*****选择操作:");
scanf("%d",&i);
break;
case 5:
fun5(G);
printf("\n*****选择操作:");
scanf("%d",&i);
break;
case 6:
fun6(G);
printf("\n*****选择操作:");
scanf("%d",&i);
break;
case 7:
fun7(G);
printf("\n*****选择操作:");
scanf("%d",&i);
break;
case 8:
exit(8);
default:
break;
}
}
return 0;
}
七、运行实例
(仅提供部分截图)