《数据结构课程设计》求最佳路径

来源:互联网 发布:ember.js 开发工具 编辑:程序博客网 时间:2024/05/22 15:26

 

 

 

 

 

 

《数据结构课程设计》
 

 

 

 

 

 

课程题目

《求最佳路径》

课程编号

j1620102

学生姓名

纪健欣

所在专业

信息管理与信息系统

所在班级

信管1134

任课老师

     易学明

实习时间

   第1617

设计成绩

 

老师评语

 

 

 

 

 

 


数据结构课程设计说明书

1.课程设计题目

GDOU是真是一个好地方,校园如一座大花园,美丽而宽广。校园有许多建筑如教学楼、饭堂、宿舍楼、图书馆、体育馆、运动场、商业街、医院等,还有一些著名的风景点。现请根据学校的平面图,找出一些重要的场所,画出学校的平面图(场所可以根据其重要性适当减少),根据实际画出不同点间的路径,并估算每两个场所间的路径长。请设计数据结构并编程,当给出一个出发点和要到达另外一个场所的信息时,请给出最佳路径,并输出路径相关信息。 

 

2.课程设计功能

① 简单地存储学校地图

② 查找出一处建筑到其他所有建筑的最佳路径和最佳路径的长度

③ 查找出两处建筑之间的最佳路径和最佳路径的长度

 

3.课程设计要求

根据不同建筑之间的路径,估算每两个建筑之间的路径长度。根据已给出的一个出发点,找出到另一建筑或其他点的最佳路径,并输出路径的相关信息

 

4.需求分析

① 查找一处建筑到其他所有建筑的最佳路径和最佳路径的长度,也就是求一点到其他点的最短路径问题,可以采用迪杰斯特拉算法(Dijkstra's Algorithm

② 学校地图反映出各个建筑之间的位置距离,可以利用邻接矩阵来存储

 

5.代码

main.cpp //main.cpp  #include "GraphList.h"  int main()  {      GraphList graphList;//图      int choice;//存放用户的选择      char element_1, element_2;      int locate_1, locate_2;      int Path[MAX_VERTEX_NUM], Dest[MAX_VERTEX_NUM];      bool DIJFlag = false;//标记是否进行过了DIJ算法      createGraph(graphList);      cout << "************************************************************************" << "\n广东海洋大学主要建筑如下:" << "\n a.教学主楼,  b.商业中心,  c.体育馆,  d.钟海楼,\n e.图书馆,    f.第三饭堂,  g.科技楼,  h.宿舍\n"   << "\n"         << "\n------------------------------------------------------------------------"           << "\n--广东海洋大学地图如下所示:";      printGraph(graphList);  cout << "\n" << "\n------------------------------------------------------------------------"           << "\n--主菜单:"           << "\n--1.查询从某点到其他点的最佳路径."           << "\n--2.查询两点之间所有路径和最佳路径."           << "\n--0.退出."           << "\n\n-------------------------------------------"           << "\n--请输入您的选择(1/2/0): ";      cin >> choice;      while(choice != 0)      {          switch(choice)          {          case 1:  cout << "\n--请输入图中的一个点(e.g.: a): ";              cin >> element_1;              if((locate_1=findNode(graphList, element_1)) == -1) return 0;              if(!DIJFlag)//如果没有进行了DIJ算法查找最短路径              {                  shortestPath_DIJ(graphList, locate_1, Path, Dest);                  DIJFlag = true;              }              printShortestPath_DIJ(graphList, locate_1, Path, Dest);              break;          case 2:  cout << "\n--请输入图中的两个点(e.g.: a b): ";              cin >> element_1 >> element_2;              locate_1 = findNode(graphList, element_1);              locate_2 = findNode(graphList, element_2);              if((locate_1==-1) || (locate_2==-1)) return 0;              if(!DIJFlag)//如果没有进行了DIJ算法查找最短路径              {                  shortestPath_DIJ(graphList, locate_1, Path, Dest);                  DIJFlag = true;              }  cout << " 点 "   << element_1   << " 和 "   << " 点 "   << element_2   << "之间的路径情况: ";              allPath_2Vexs(graphList, locate_1, locate_2);//输出所有路径              cout << "\n--------------------------------------";              printShortestPath_2Vexs(graphList, locate_1, locate_2, Path, Dest);              break;          default:  cout << "--您的输入有误!!!自动退出!!!\n";              return 0;          }          cout << "\n\n-------------------------------------------"       << "\n--请输入您的选择(1/2/0): ";          cin >> choice;      }      deleteGraph(graphList);//删除图,防止内存泄露      return 0;  }  GraphList.cpp//***************  GraphList.cpp  #include "GraphList.h"  //查找顶点,工具方法,查找element是否存在于graphlist中,返回element的位置i  int findNode(GraphList &graphList, char element)  {      int i;      for(i=0; i<graphList.vertexNum; i++)      {          if(element == graphList.vertexList[i].data)          {              break;          }      }      if(i >= graphList.vertexNum)      {  cout << "找不到该元素!!!\n";          return -1;      }      return i;  }  //创建图,并执行初始化  所有顶点以及边都在程序内部定义  bool createGraph(GraphList &graphList)  {      //初始化定点表      graphList.vertexNum = 0;//顶点数      graphList.edgeNum = 0;//边数      int value = 0;//暂时存放从邻接矩阵中读取的数值      char vexArray[MAX_VERTEX_NUM] = {'a','b', 'c', 'd', 'e', 'f', 'g', 'h'};//顶点的数组//建立顶点表 vertexList      for(int v=0; v<MAX_VERTEX_NUM; v++)      {          if(vexArray[v] != '\0') graphList.vertexNum++;//如果第v+1个顶点不为空值,则顶点数+1          graphList.vertexList[v].data = vexArray[v];//把顶点表中v的数据赋给顶点数组中的v          graphList.vertexList[v].firstarc = NULL;      }      //初始化边表 Edge      int edgeArray[MAX_VERTEX_NUM][MAX_VERTEX_NUM] = {//初始化邻接矩阵          //0,1,2,3,4,5,6,7          {0,55,0,40,50,0,0,0},//0          {55,0,10,0,0,0,0,0},//1          {0,10,0,20,0,0,0,0},//2          {40,0,0,0,45,75,25,110},//3          {50,0,20,45,0,0,60,0},//4          {0,0,0,75,0,0,70,60},//5          {0,0,0,25,60,70,0,90},//6          {0,0,0,110,0,60,90,0},//7      };      for(int i=0; i<graphList.vertexNum; i++)      {          EdgeNode *temp = NULL;//存放临时的节点          EdgeNode *Node = NULL;//存放新生成的节点          for(int j=0; j<graphList.vertexNum; j++)          {  //edgeArray 边的数组            if((value = edgeArray[i][j]) != 0)//有边              {                  if(!(Node = new EdgeNode))                  {                      cerr << "No Enough Memory!";//cerr:不经过缓冲区,直接把内容输出到显示屏上                      exit(1);//exit(0)正常退出, exit(1)错误退出,                  }                  Node->adjvexLocate = j;//把节点在定点表中的位置赋给j                  Node->value = value;                  Node->next = NULL;//生成节点                  graphList.edgeNum++;                  if(graphList.vertexList[i].firstarc == NULL)//第一个节点                  {                      graphList.vertexList[i].firstarc = Node;                      temp = Node;                  }                  else                  {                      temp->next = Node;                      temp = Node;                  }              }          }      }      return true;  }  //输出图bool printGraph(GraphList &graphList)  {      EdgeNode *temp = NULL;      if(!&graphList)  return false;      for(int i=0; i<graphList.vertexNum; i++)      {          cout << "\n"   << graphList.vertexList[i].data   << ": ";          temp = graphList.vertexList[i].firstarc;          while(temp)          {              cout << " ("   << graphList.vertexList[i].data   << ","   << graphList.vertexList[temp->adjvexLocate].data   << ","                   << temp->value   << ") ";              temp = temp->next;          }      }  return true;  }  //单源最短路径算法/*  vex:源点  i:某一终点  Dest[i]:源点vex到点i的最短路径的长度  Path[i]:源点vex到点i的最短路径  */  void shortestPath_DIJ(GraphList &graphList, int vex, int Path[], int Dest[])  {      bool finalShortest[MAX_VERTEX_NUM];      EdgeNode *temp = NULL;      int minValue = INFINITY;//用作寻找最小的路径权值      int v = 0;//记录每一次寻找的最小路径终点的位置      for(int i=0; i<graphList.vertexNum; i++)//第一步初始化      {          finalShortest[i] = false;          Path[i] = -1;//没有前驱,即没有路径          Dest[i] = INFINITY;//存放vi与给出的源点之间的最短路径      }      finalShortest[vex] = true;      Dest[vex] = 0;//修改源点的值      Path[vex] = -1;      temp = graphList.vertexList[vex].firstarc;      while(temp)      {          Dest[temp->adjvexLocate] = temp->value;          Path[temp->adjvexLocate] = vex;//前驱          temp = temp->next;      }//初始化完成        for(int i=1; i<graphList.vertexNum; i++)//执行n-1次循环,对剩余的n-1个顶点操作      {          minValue = INFINITY;          for(int j=0; j<graphList.vertexNum; j++)          {              if(!finalShortest[j])//还没有求出最短路径              {                  if(Dest[j] < minValue)                  {                      v = j;                      minValue = Dest[j];                  }              }          }          finalShortest[v] = true;//将此终点加入已求出最短路径的集合          //更新参数          for(int j=0; j<graphList.vertexNum; j++)          {              int vValue = INFINITY;//存放v 与 j之间的权重              temp = graphList.vertexList[v].firstarc;//一句话如果放错位置就会出现无法预料的错误!              while(temp)              {                  if(temp->adjvexLocate == j)                  {                      vValue = temp->value;                      break;                  }                  temp = temp->next;              }              if(!finalShortest[j] && (minValue+vValue<Dest[j]))              {                  Dest[j] = minValue + vValue;//更新为更小的权重                  Path[j] = v;//更新前驱节点              }          }      }  }  //输出生成的单源最短路径  /*  vex:源点  i:某一终点  Dest[i]:源点vex到点i的最短路径的长度  Path[i]:源点vex到点i的最短路径  */  void printShortestPath_DIJ(GraphList &graphList, int vex, int Path[], int Dest[])  {      int pre = 0;  cout<< "从点"  << graphList.vertexList[vex].data  << "到其他点的最佳路径为:";      for(int i=0; i<graphList.vertexNum; i++)      {          if(Dest[i] >= INFINITY || i == vex) continue;          cout << "\n\t("   << graphList.vertexList[vex].data   << "->"   << graphList.vertexList[i].data               << "):  路径长度 = "   << Dest[i]   << "\t路径: "   << graphList.vertexList[i].data;          pre = Path[i];          while(pre != -1)          {              cout << " "   << graphList.vertexList[pre].data;              pre = Path[pre];          }      }  }  //输出两点之间最短路径及距离  /*  vex1:源点1vex2:源点2i:vex1或vex2  Dest[i]:源点vex1和源点2之间的最短路径的长度  Path[i]:源点vex1和源点2之间的最短路径  */  void printShortestPath_2Vexs(GraphList &graphList, int vex1, int vex2, int Path[], int Dest[])  {      int pre = 0;  cout << "\n点"   << graphList.vertexList[vex1].data   << "和点"   << graphList.vertexList[vex2].data   << "之间的最佳路径:";    for(int i=0; i<graphList.vertexNum; i++)      {          if(i == vex2)          {  cout << "\n\t("   << graphList.vertexList[vex1].data   << "->"   << graphList.vertexList[vex2].data   << "):  路径长度 = "   << Dest[i]   << "\t路径: "   << graphList.vertexList[i].data;              pre = Path[i];              while(pre != -1)              {                  cout << " "   << graphList.vertexList[pre].data;                  pre = Path[pre];              }              return;          }      }  }  //删除图bool deleteGraph(GraphList &graphList)  {      if(graphList.vertexNum == 0) return false;      EdgeNode *temp = NULL;      for(int i=0; i<graphList.vertexNum; i++)//定点表中每个顶点      {          if((temp = graphList.vertexList[i].firstarc) == NULL) continue;          while(temp)          {              graphList.vertexList[i].firstarc = temp->next;              delete temp;              temp = graphList.vertexList[i].firstarc;          }      }      return true;  }  //任意两点之间的所有路径void allPath_2Vexs(GraphList &graphList, int startVex, int endVex)  {      if(startVex == endVex)      {          return;      }      bool status[MAX_VERTEX_NUM] = {false};//标记点被访问的状态      vector<int> pathStack;//记录访问到节点的位置      int length = 0;      visit(graphList, startVex, endVex, status, pathStack, length);  }  //递归访问每个元素  void visit(GraphList &graphList, int vex, int endVex, bool status[], vector<int> &pathStack, int length)//对vex点进行访问  {      if(vex == endVex)//找到了终点      {  cout << "\n\t路径长度 = "   << length   << "\t路径: ";          for(unsigned int i=0; i<pathStack.size(); i++)          {              cout << " "   << graphList.vertexList[pathStack[i]].data;          }          cout << " " << graphList.vertexList[endVex].data;          return;      }      status[vex] = true;      pathStack.push_back(vex);      EdgeNode *current = NULL;      for(current=graphList.vertexList[vex].firstarc; current!=NULL; current = current->next)      {          if(!status[current->adjvexLocate])          {              length += current->value;              visit(graphList, current->adjvexLocate, endVex, status, pathStack, length);          }      }      status[vex] = false;//修改标志      pathStack.pop_back();//回溯  }GraphList.h  //******************        GraphList.h  #ifndef GRAPHLIST_H_INCLUDED  #define GRAPHLIST_H_INCLUDED  #include <iostream>  #include <string>  //字符串类#include <cstdlib>  //引入文件的输入输出的函数库#include <stack>  //STL 堆栈容器#include <vector>  //STL 动态数组容器using namespace std;  #define MAX_VERTEX_NUM 8//最大支持的节点数  #define INFINITY 1000//表示无穷大  typedef int EdgeValueType;//定义边权重类型  typedef char VertexType;//定义顶点表顶点的内容类型  typedef struct EdgeNode//边表节点  {      int adjvexLocate;//该弧所指向的顶点在定点表中的位置      EdgeValueType value;//权重      EdgeNode *next;//指向下一个节点  } EdgeNode;  typedef struct VertexNode//顶点表  {      VertexType data;//顶点名称      EdgeNode *firstarc;//指向第一条依附顶点的指针  } VertexNode, VertexList[MAX_VERTEX_NUM]; //顶点节点,顶点表  typedef struct GraphList  {      VertexList vertexList;//建立顶点表      int vertexNum, edgeNum;//整个图中存放顶点、边的个数  } GraphList;  //函数声明  int findNode(GraphList &graphList, char element);//查找顶点,工具方法  bool createGraph(GraphList &graphList);//创建图    bool printGraph(GraphList &graphList);//输出图  void shortestPath_DIJ(GraphList &graphList, int vex, int P[], int D[]);//单源最短路径算法  void printShortestPath_DIJ(GraphList &graphList, int vex, int Path[], int Dest[]);//输出生成的单源最短路径  void printShortestPath_2Vexs(GraphList &graphList, int vex1, int vex2, int Path[], int Dest[]);//输出两点之间最短路径及距离  void allPath_2Vexs(GraphList &graphList, int startVex, int endVex);//任意两点之间的所有路径  void visit(GraphList &graphList, int vex, int endVex, bool status[], vector<int> &pathStack, int length);//递归访问每个元素  bool deleteGraph(GraphList &graphList);//删除图,防止内存泄露  #endif // GRAPHLIST_H_INCLUDED  


6.运行截图



7.收获和体会

通过这次数据结构的课程设计,我进行了一次实践,运用数据结构的知识,针对具体问题,设计了合理的数据结构,确定相应的存储过程,并设计具体操作算法,实现了相应的功能。虽然平时也有实验,但那些只是普通的一小段而已,没有编写整个系统的机会。这次课程设计给了我一个把理论与实践相结合的机会,让我学有所用,学以致用。

这次课程设计也让我意识到一个问题——把如何把实际问题更好的融入到系统中。我认为,这个问题没有最佳答案,因为没有最好,只有更好。当你优化一个方案后,觉得已经很完美了,但是其实还有更好的方案,只是你没有找到而已。这是一个无止尽的专研过程,也是一个无限的学习过程。人生也是如此,走到哪,学到哪,活到老,学到老。

 

 

8.不足

代码编写没有特别完善,一些问题处理的也不够好。对于代码的注释也不够多,不够完整。以后做系统的时候要注意这些问题,吸取教训,好好改正,争取把代码写得更好。


0 0
原创粉丝点击