• 顶点间最短路径长度之探寻算法


    1.最短路径概念

             在一个无权的图中,若从一顶点到另一顶点存在着一条路径,则称该路径长度为该路径上所经过的边的数目,它等于该路径上的顶点数减1。由于从一顶点到另一顶点可能存在着多条路径,每条路径上所经过的边数可能不同,即路径长度不同,我们把路径长度最短(即经过的边数最少)的那条路径叫做最短路径,其路径长度叫做最短路径长度或最短距离。
      
            对于带权的图,考虑路径上各边上的权值,则通常把一条路径上所经边的权值之和定义为该路径的路径长度或称带权路径长度。从源点到终点可能不止一条路径,把带权路径长度最短的那条路径称为最短路径,其路径长度(权值之和)称为最短路径长度或者最短距离。

    2.Dijkstra狄克斯特拉算法

         思路

           创建标号表flag, index为节点编号,flag[index]表征节点是否已经访问。创建矩阵path,path[index]的值为,起点from到顶点index的最短路径中到顶点index的上一个节点,-1表示起点到当前节点无路径。创建矩阵dist,dist[index]的值为,起点form到顶点index的最短路径。

           设定起点为from。

           (1)初始化,除flag[from]之外的值均为false,代表尚未探寻成功最短路径。初始化dist的值为起点直接到当前节点的路径长度。初始化path的所有值为from,若起点到该顶点无路径,设定为-1。

           (2) 进行n-1次循环:

               a.寻找最短路径顶点:遍历寻找dist中,值最小且尚未探寻成功最小路径的顶点并记录其标号index。

               b.标记最短路径顶点:flag[index]为true.代表到该顶点的最小路径该已经探寻成功。

               c.更新剩余顶点的最短距离矩阵dist和路径矩阵path:遍历比较以index为中继点到剩余顶点的距离,和当前记录的最小距离dist。若前者小,则更新最小距离,并将path的对应值更新为中继点标号index。


         特点:

            (1).Dijkstra 算法中的两重循环都是关于n的,所以时间复杂度为:O(n.^2)。由于需要辅助标记矩阵flag,空间复杂度为O(n).

            (2).仅仅适用于正权值图


         代码

    //狄克斯特拉算法求最短路径
    // adjMatrix--邻接矩阵
    // n--顶点总数
    // from--起始节点数
    //path[index]的值为,起点from到顶点index的最短路径中到顶点index的上一个节点,-1表示起点到当前节点无路径
    //dist[index]的值为,起点form到顶点index的最短路径
    
    void dijkstra(int** adjMatrix,int n,int from,int* path,int* dist){
    
    	bool* flag=new bool[n];//顶点是否已经探寻
    
    	//initialization
    	for(int i=0;i<n;i++){
    		dist[i]=adjMatrix[from][i];
    		flag[i]=false;
    		if(i!=from&&dist[i]<MAX)
    	     	   path[i]=from;
    		else
    		   path[i]=-1;//代表无路径
    	}
    	dist[from]=0;
    	flag[from]=true;
    
    	int minDist,minIndex;
    	for(int k=1;k<n;k++){//主循环,还有n-1个顶点需要探寻路径
    
    	   //寻找dist当前最短路径并记录标号
    	   minDist=MAX;
    	   minIndex=-1;
    	   for(int i=0;i<n;i++)
    		if(!flag[i]&&dist[i]<minDist){
    			  minDist=dist[i];
    			  minIndex=i;
    		}
    
               flag[minIndex]=true;//代表顶点minIndex的最短路径已经探寻成功
    
    	   //以顶点minIndex为中继点,探寻到其余为探寻顶点的最短路径并更新dist和path
    	   for(int i=0;i<n;i++)
    		   if(!flag[i]&&(minDist+adjMatrix[minIndex][i])<dist[i]){
    			  dist[i]=minDist+adjMatrix[minIndex][i];
    			  path[i]=minIndex;
    	   }
         }
    }


    3.Floyd弗洛伊德算法和顶点间的最短路径

         思路

                   (1)初始化距离矩阵dist和路径矩阵path

                   (2)循环0:k,对于每一个路径点[i][j](排除对角线点,自己以自己为中继的点)

                       a.dist[i][j]=min{ dist[i][j], dist[i][k]+dist[k][j]},即每次保证当添加k为中继点时,取路径最短的。

                       b.若更新成功,则path[i][j]=path[i][k]。path[i][j]中的值为i到j的最短路径中,i之后顶点的序号。由于此时k为中继点,则可以把路径分为2段,且path[i][j]=path[i][k]无疑问。

         分析

                    时间复杂度为O(n.^3),空间复杂度为O(n.^2)

         代码

    //floyd算法求点之间的最短路径
    void floyd(int adjMatrix[4][4],int path[4][4],int dist[4][4]){
    	for(int i=0;i<4;i++)
    		for(int j=0;j<4;j++){
    			path[i][j]=j;//初始化,表示i到j的路径的下一顶点
    			dist[i][j]=adjMatrix[i][j];//初始化
    		}
            for(int k=0;k<4;k++){
    	  for(int i=0;i<4;i++)
    		for(int j=0;j<4;j++){
    			if(i==k||j==k||i==j) continue;
    			if(dist[i][j]>dist[i][k]+dist[k][j]){
    				dist[i][j]=dist[i][k]+dist[k][j];//更新最短距离
    				path[i][j]=path[i][k];//更新路径
    			}
    		} 
       }
    }
    void main(){
    	int adjMatrix[4][4]={{0,1,100,4},{100,0,9,2},{3,5,0,8},{100,100,6,0}};
    
    	int path[4][4],dist[4][4];
    	floyd(adjMatrix,path,dist);
    
    	for(int i=0;i<4;i++)
    		for(int j=0;j<4;j++){
    			if(i!=j){
    			  cout<<i<<"->"<<j<<":  ";
    			  if(dist[i][j]>=100)
    				  cout<<"不存在路径"<<endl;
    			  else{
    				  cout<<"dist: "<<dist[i][j]<<",path: ";
    				  int pre=i;
    				  while(pre!=j){
    					  cout<<pre<<"--";
    					  pre=path[pre][j];
    				  }
    				  cout<<j<<endl;
    			  }
    		}
    	}
    }





  • 相关阅读:
    使用npm安装一些包失败了的看过来(npm国内镜像介绍)(解决生成空的abp模板项目一直卡在还原cpm包中)
    .NET CORE 发布到IIS问题 HTTP ERROR 500.30
    .NET Core默认不支持GB2312,使用Encoding.GetEncoding(“GB2312”)的时候会抛出异常。
    .net c# 文件分片/断点续传之下载--客户端
    aspnetcore 实现断点续传
    C# 反射获取属性值、名称、类型以及集合的属性值、类型名称
    C# 3Des两种加密方式 (对应java中的desede/CBC/PKCS5Padding加密)
    Asp.NetCore3.1中多次读取Request.Body
    ASP.NET Core 2.0系列学习笔记-DI依赖注入
    C# Newtonsoft.Json JObject合并对象整理
  • 原文地址:https://www.cnblogs.com/engineerLF/p/5393033.html
Copyright © 2020-2023  润新知