最短路径—Dijkstra算法

最近在看DP相关的知识, 遇到图的最短路径 重新看了一遍 ,自己写了的code 测试了一下 。

算法步骤:

a.初始时,S只包含源点,即S={v},v的距离为0。U包含除v外的其他顶点,即:U={其余顶点},若v与U中顶点u有边,则<u,v>正常有权值,若u不是v的出边邻接点,则<u,v>权值为∞。

b.从U中选取一个距离v最小的顶点k,把k,加入S中(该选定的距离就是v到k的最短路径长度)。

c.以k为新考虑的中间点,修改U中各顶点的距离;若从源点v到顶点u的距离(经过顶点k)比原来距离(不经过顶点k)短,则修改顶点u的距离值,修改后的距离值的顶点k的距离加上边上的权。

d.重复步骤b和c直到所有顶点都包含在S中


算法具体描述参考 http://www.cnblogs.com/biyeymyhjob/archive/2012/07/31/2615833.html


/*
 *
 * int Dij_array[6][6] ={{  0,  6,  3,999,999,999},
			 {6  ,  0,  2,  5,999,999},
			 {3  ,  2,  0,  3,  4,999},
			 {999,  5,  3,  0,  2,  3},
			 {999,999,  4,  2,  0,  5},
			 {999,999,999,  3,  5,  0}};
 *
 *
 * */
void Dijkstra_demo(int a[6][6] ,int dim){

	int row ,col, keyPath, nextRow;
	keyPath = 0 ;
	nextRow = 0 ;
	int Flag[dim] ={1};
	int minInEachRow[dim] ={};
	int addVolume = 0;

	for(row = 0; row< dim ;row++){

		int minInRow = 999;
		nextRow = 1;
		Flag[row] = 1;
		minInEachRow[0] = 3;//hard code here

//        for(int i =0 ; i<6 ; i++){
//        	printf("flagbbb = %d \t ",Flag[i]);
//        }
//        printf("current row = %d \n ",row);


		for(col = 1; col <dim ; col++){

		     if( (Flag[col]==0)&&(col != row ) &&( minInRow > a[row][col] )) {
		    	 minInRow = a[row][col] ;
		    	 nextRow  = col;

		     }

		}


	//	if(row == 0)keyPath =  minInRow ;
		keyPath = keyPath  + minInRow ;
		printf("keyPath 1  = %d \t",keyPath );
		int tempKey =0;
		int addVolumeIndex = 0;
		for(int i = 1 ; i<6 ; i++){

			if(Flag[i]==1) {
				tempKey = a[i][0] + a[i][nextRow];
				printf("ccctempKey = %d  %d ,%d  i = %d\t",tempKey,a[i][0],a[i][nextRow] , i );
			    if(tempKey < keyPath) {
			    	keyPath = tempKey;
			    	addVolume = a[i][nextRow];
			    }

			}

	    }
		printf("\n" );
		minInEachRow[nextRow] = addVolume ;// recorder for print path
		a[nextRow][0] = keyPath ;

		//if(a[nextRow][0] != keyPath) PrintFlag[i]=2;
//		for(int i = 0 ; i<6 ; i++){
//
//
//			printf("a[i]= %d ",a[i][0] );
//
//	    }
//

//		if(row == 0){
//			keyPath = keyPath  + minInRow ;
//		}
//		else{
//	       	if(a[row][0] > keyPath)
//	           a[row][0] = keyPath;
//		}
//
//
//        int minInCol = 999;  // skip a[0][0]
//        for(int i =1 ; i<6 ; i++){
//        	if((Flag[i]==1) && (minInCol > a[i][0]) )minInCol= a[i][0];
//
//        }
//        if(row > 0){
//        	keyPath = minInRow + minInCol ;
//        	if(a[nextRow][0] > keyPath)
//        	a[nextRow][0] = keyPath;
//
//        }




        printf("nextRow = %d in currentRow = %d , minInRow =%d ,minInCol =%d  \n",nextRow , row ,minInRow ,a[row][0]);

        if(keyPath > 999 )break;



        if(Flag[nextRow] == 0 )
          row = nextRow -1; // for wil add one in next loop

//        for(int i =0 ; i<6 ; i++){
//        	printf("flag = %d \t ",Flag[i]);
//        }

        printf("keyPath = %d  ,row = %d \n\n", keyPath ,row);
        printf("===========================\n");

        if(nextRow  == 5 ){

        	for(int i = 0 ;i < 6 ;i++){
        		printf(" %d <===" ,minInEachRow[i]);
        	}

        	printf("=========the KeyPath is %d= addVolume =%d=================\n" , keyPath ,a[0][0]);
        	printf("=========the Path is = 5 << ");

        	for(int i = 5 ;i >=0 ;i--){

        		if(a[i][0] == (keyPath -addVolume )){

        			printf(" %d <===" ,i);
        			keyPath = keyPath -addVolume ;
        			addVolume = minInEachRow[i];
        		}

        	}printf(" 0 .... end %d  %d\n" ,keyPath , addVolume );

        	break ;
        }
	}



}






计算的步骤就是 

1.从6x6的矩阵第一行找出最小的数值,记录出列号即要跳过去的行号 nextRow

2.在新的行内,标记行号Flag[row] 并且在本行内找 “行号没被标记过”的最小值 minInRow记录出列号即要跳过去的行号,更新keypath

3.循环标记过的行  比较 (a[row][0] +a[row][nextRow]) 和keypath 。如果小于keypath ,就说明有比  keypath 更短的路径,更新后方在

    a[row][0] 中, 并将增量addVolume 记录下来, 用来打印路径。

4 goto第二步

 * int Dij_array[6][6] ={{  0,  6,  3,999,999,999},
			 {6  ,  0,  2,  5,999,999},
			 {3  ,  2,  0,  3,  4,999},
			 {999,  5,  3,  0,  2,  3},
			 {999,999,  4,  2,  0,  5},
			 {999,999,999,  3,  5,  0}};

数据说明 999是不可到的意思,0是自己,a[row][0] 用来记录到本行的最短距离

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值