c/c++常用算法(15) -- 经典数据结构(城市之间的最短距离问题)

2014-11-24 07:44:48 · 作者: · 浏览: 0

一、最短总距离算法:


1.描述


我们先来分析一下这个问题。某个地区n个城市构成一个交通图,我们可以使用图结构来描述这个问题,其对应关系如下:

每个城市代表一个图中的一个顶点。两个顶点之间的边就是两个城市之间的路径,边的权值代表了城市间的距离。

这样,求解各个城市之间的最短总距离问题就归结为该图的最小生成树问题。


2.最小生成树


一个有 n 个结点的连通图的生成树是原图的极小连通子图,且包含原图中的所有 n 个结点,并且有保持图连通的最少的边。如图:


\



< http://www.2cto.com/kf/ware/vc/" target="_blank" class="keylink">vcD4KPGgyPjMuu/mxvsu8z+s8L2gyPgo8cD48YnI+CjwvcD4KPHA+ICAgICAgICC82cnoR6O9KFajrEUpysfBrM2otcSjrFRFysdHyc/X7tChyfqzycr31tCx37XEvK+6z6Gjy+O3qLTTVaO9e3UwfaOodTChylajqaGiVEWjvXt9v6rKvKGj1ti4tNa00NDPwsHQstnX96O6PGJyPgogICAgICAgICAgINTay/nT0HWhylWjrHahylajrVW1xLHfKHWjrHYpocpF1tDV0tK7zPXIqCYjMjA1NDA71+7QobXEsd8odTAsdjApsqLI67yvus9URdbQo6zNrMqxdjCyosjrVaOs1rG1vVajvVXOqta5oaM8YnI+CiAgICAgICAgICAgtMvKsaOsVEXW0LHY09BuLTHM9bHfo6xUPShWo6xURSnOqke1xNfu0KHJ+rPJyvehozwvcD4KPHA+PGJyPgo8L3A+CjxoMj40Lsq1z9a0+sLrKNfutszX3L7gwOvL47eoKTwvaDI+CjxwPjwvcD4KPHByZSBjbGFzcz0="brush:java;">#include #include #include #define MaxNum 20 //图的最大顶点数 #define MaxValue 65535 //最大值 #define USED 0; //已选用顶点 #define NoL -1 //非邻接顶点 typedef struct { char Vertex[MaxNum]; //保存顶点信息(序号或字母) int GType; //图的类型(0:无向图,1) int VertexNum; //顶点的数量 int EdgeNum; //边的数量 int EdgeWeight[MaxNum][MaxNum]; //保存边的权 int isTrav[MaxNum]; //定义邻接矩阵图结构 }GraphMatrix; void CreateGraph(GraphMatrix *GM) { int i,j,k; int weight; char EstartV,EendV; std::cout<<"输入图中各顶点信息\n"; for (i = 0; i VertexNum; i++) { getchar(); printf("第%d个顶点:",i+1); scanf("%c",&(GM->Vertex[i])); } std::cout<<"输入构成各边的顶点及权值:\n"; for (k = 0; k EdgeNum; k++) { getchar(); printf("第%d条边:",k+1); scanf("%c %c %d",&EstartV,&EendV,&weight); for ( i= 0; EstartV != GM->Vertex[i]; i++); for ( j= 0; EendV != GM->Vertex[j]; j++); GM->EdgeWeight[i][j] = weight; if (GM->GType == 0) //若是无向图 { GM->EdgeWeight[j][i] = weight; } } } void ClearGraph(GraphMatrix *GM) { int i,j; for (i=0; i VertexNum; i++) { for (j=0; j VertexNum; j++) { GM->EdgeWeight[i][j] = MaxValue; } } } void OutGraph(GraphMatrix *GM) { int i,j; for (j=0; j VertexNum; j++) { printf("\t%c",GM->Vertex[j]); } std::cout<<"\n"; for (i=0; i VertexNum; i++) { printf("%c",GM->Vertex[i]); for (j=0; j VertexNum; j++) { if (GM->EdgeWeight[i][j] == MaxValue) { printf("\tZ"); //以Z表示无穷大 } else { printf("\t%d",GM->EdgeWeight[i][j]); //输出边的权值 } } std::cout<<"\n"; } } void PrimGraph(GraphMatrix GM) //最小生成树算法 { int i,j,k,min,sum; int weight[MaxNum]; //权值 char vtempx[MaxNum]; //临时顶点信息 sum = 0; for(i = 1; i 0) //到具有更小权值的未使用边 { min = weight[j]; //保存权植 k = j; //保存邻接点序号 } } sum +=min; //权值累加 printf("(%c,%c),",vtempx[k],GM.Vertex[k]); //输出生成树一条边 vtempx[k] = USED; weight[k] = MaxValue; for (j = 0; j
演示结果:


\


演示效果图:


\


二、最短路径


1.描述


求解城市之间的最短距离是一个非常实际的问题。其大意如下:

某个地区有n个城市,如何选择路线使某个城市到某个指定城市的距离最短


注:这里需要求解的最短路径指两个城市之间的最短距离,面不是所有城市之间最短总距离。


2.基本思想


算法步骤如下:


1. 初始时令 S={V0},T={其余顶点},T中顶点对应的距离值
若存在 ,d(V0,Vi)为 弧上的权值
若不存在 ,d(V0,Vi)为∞
2. 从T中选取一个其距离值为最小的顶点W且不在S中,加入S
3. 对其余T中顶点的距离值进行修改:若加进W作中间顶点,从V0到Vi的距离值缩短,则修改此距离值
重复上述步骤2、3,直到S中包含所有顶点,即W=Vi为止


3.实现代码

#include 
  
   
#include 
   
     #include 
    
      #define MaxNum 20 //图的最大顶点数 #define MaxValue 65535 //最大值 int path[MaxNum]; //两点经过的顶点集合的数组 int tmpvertex[MaxNum]; //最短路径的起始点集合 #define USED 0; //已选用顶点 #define NoL -1 //非邻接顶点 typedef struct { char Vertex[MaxNum]; //保存顶点信息(序号或字母) int GType; //图的类型(0:无向图,1) int VertexNum; //顶点的数量 int EdgeNum; //边的数量 int EdgeWeight[MaxNum][MaxNum]; //保存边的权 int isTrav[MaxNum]; //定义邻接矩阵图结构 }GraphMatrix; void CreateGraph(GraphMatrix *GM) { int i,j,k; int weight; char EstartV,EendV; std::cout<<"输入图中各顶点信息\n"; for (i = 0; i
     
      VertexNum; i++) { getchar(); printf("第%d个顶点:",i+1); scanf("%c",&(GM->Vertex[i])); } std::cout<<"输入构成各边的顶点及权值:\n"; for (k = 0; k 
      
       EdgeNum; k++) { getchar(); printf("第%d条边:",k+1); scanf("%c %c %d",&EstartV,&EendV,&weight); for ( i= 0; EstartV != GM->Vertex[i]; i++); for ( j= 0; EendV != GM->Vertex[j]; j++); GM->EdgeWeight[i][j] = weight; if (GM->GType == 0) //若是无向图 { GM->EdgeWeight[j][i] = weight; } } } void ClearGraph(GraphMatrix *GM) { int i,j; for (i=0; i
       
        VertexNum; i++) { for (j=0; j
        
         VertexNum; j++) { GM->EdgeWeight[i][j] = MaxValue; } } } void OutGraph(GraphMatrix *GM) { int i,j; for (j=0; j
         
          VertexNum; j++) { printf("\t%c",GM->Vertex[j]); } std::cout<<"\n"; for (i=0; i
          
           VertexNum; i++) { printf("%c",GM->Vertex[i]); for (j=0; j
           
            VertexNum; j++) { if (GM->EdgeWeight[i][j] == MaxValue) { printf("\tZ"); //以Z表示无穷大 } else { printf("\t%d",GM->EdgeWeight[i][j]); //输出边的权值 } } std::cout<<"\n"; } } void DisMin(GraphMatrix GM,int vend) //最短路径算法 { int weight[MaxNum]; //某终止点到各顶点的最短路径长度 int i,j,k,min; vend--; for (i =0; i
            
             0) //有效权值 { path[i] = vend; //保存边 } } for (i=0; i
             
              演示结果: 
              

\


演示效果图:




参考书籍:《C/C++常用算法手册》