zoukankan      html  css  js  c++  java
  • 单源最短路径(dijkstra算法)php实现

    做一个医学项目,当中在病例评分时会用到单源最短路径的算法。单源最短路径的dijkstra算法的思路例如以下:
    如果存在一条从i到j的最短路径(Vi.....Vk,Vj),Vk是Vj前面的一顶点。那么(Vi...Vk)也必然是从i到k的最短路径。Dijkstra是以最短路径长度递增,逐次生成最短路径的算法。比如:对于源顶点V0,首先选择其直接相邻的顶点中长度最短的顶点Vi,那么当前已知可得从V0到达Vj顶点的最短距离dist[j]=min{dist[j],dist[i]+cost[i][j]}。如果G=<V, E>,源点为V0,U={V0}表示已经标记过的顶点集合,dist[i]记录V0到i的最短距离,cost[i][j]表示边i到j的开销。   
    1.从V-U中选择使dist[i]值最小的顶点i,将i增加到U中;

    2.更新与i直接相邻顶点的dist值。(dist[j]=min{dist[j],dist[i]+cost[i][j]})

    3.知道U=V,停止。

    利用php特有的性质,其代码例如以下:

    function dijkstra(){		
    	$node_info_arr=array(	//结点的邻接表结构
    		array(
    			'node_id'=>0,		//某个结点的id
    			'next_node'=>array(4,2,1),
    			'node_type'=>0,
    			'cost'=>array(10,30,100)
    			),
    		array(
    			'node_id'=>4,		//某个结点的id
    			'next_node'=>array(3),
    			'node_type'=>1,
    			'cost'=>array(50)
    			),
    		array(
    			'node_id'=>3,		//某个结点的id
    			'next_node'=>array(1),
    			'node_type'=>1,
    			'cost'=>array(10)
    			),
    		array(
    			'node_id'=>2,		//某个结点的id
    			'next_node'=>array(3,1),
    			'node_type'=>1,
    			'cost'=>array(60,60)
    			),
    		array(
    			'node_id'=>1,		//某个结点的id
    			'next_node'=>array(),
    			'node_type'=>2,
    			'cost'=>array()
    			)
    	);
    	
    	$start_node_id=false;		//起始结点id
    	$i_cost=array(array());	//两个节点之间的开销
    	$i_dist=array();		//起始点到各点的最短距离
    	$b_mark=array();		//是否增加了
    	foreach($node_info_arr as &$node_info){
    		if($node_info['node_type']==0){
    			$start_node_id=$node_info['node_id'];			//找到初始节点
    		}
    		foreach($node_info['next_node'] as $key=>$next_node){
    			$i_cost[$node_info['node_id']][$next_node]=$node_info['cost'][$key];
    		}
    		$i_dist[$node_info['node_id']]='INF';				//初始化为无穷大
    		$b_mark[$node_info['node_id']]=false;				//初始化未增加
    	}
    	if($start_node_id===false){
    		return '302';
    	}
    	//计算初始结点到各节点的最短路径
    	$i_dist[$start_node_id]=0;	//初始点到其本身的距离为0
    	$b_mark[$start_node_id]=true;	//初始点增加集合
    	
    	$current_node_id=$start_node_id;	//近期增加的节点id
    	$node_count=count($node_info_arr);
    	for($i=0;$i<$node_count;$i++){
    		$min='INF';								//当前节点的近期距离
    		if(is_array($i_cost[$current_node_id])){
    			foreach($i_cost[$current_node_id] as $key=>$val){
    				if($i_dist[$key]=='INF'||$i_dist[$key]>$i_dist[$current_node_id]+$val){
    					$i_dist[$key]=$i_dist[$current_node_id]+$val;
    				}
    			}
    		}
    		foreach($i_dist as $key=>$val){
    			if(!$b_mark[$key]){
    				if($val!='INF'&&($min=='INF'||$min>$val)){
    					$min=$val;
    					$candidate_node_id=$key;	//候选近期结点id
    				}
    			}
    		}
    		if($min=='INF'){
    			break;
    		}
    		$current_node_id=$candidate_node_id;
    		$b_mark[$current_node_id]=true;
    	}
    	foreach($i_dist as $key=>$val){
    		echo $start_node_id.'=>'.$key.':'.$val.'<br />';
    	}
    }

     当中样例为图:
        
    执行结果为:
        0=>0:0
        0=>4:10
        0=>3:60
        0=>2:30
        0=>1:70


  • 相关阅读:
    Django~学习计划
    在路上---学习篇(一)Python 数据结构和算法 (1)
    面向对象设计原则—单一、开闭、里氏替换原则
    flex布局实现elment容器布局
    js 面向对象的三大特性
    Http状态码大全(200、404、500等)
    HTTP常见状态码 200 301 302 404 500
    Android编程中,sp和px和dp有什么区别
    Android xml资源文件中@、@android:type、@*、?、@+含义和区别
    Android虚拟键盘上下左右键按下和弹起的响应事件
  • 原文地址:https://www.cnblogs.com/mengfanrong/p/3809896.html
Copyright © 2011-2022 走看看