php一些算法总结

1、深度优先递归遍历

/*
 *深度优先递归遍历[不重复的数字顺序排列组合]
 *@param $step 第几步
 *@param $a 数组
 *@param $book 标记
 *@param $num 统计总数
 */
function dfs($step,$a,$book,&$num){
	if($step==6+1){//到临界点终止
		for($i=1;$i<=6;$i++){
			print_r($a[$i]).' ';
		}	
		print_r('<br>');
		$num++;
		return;
	}
	for($i=1;$i<=6;$i++){
		if(!isset($book[$i])||$book[$i]==0){
			$a[$step] = $i;//表示第$step步选择了$i号
			$book[$i] = 1;//标记$i号已选择
			dfs($step+1,$a,$book,$num);//递归下一步
			$book[$i] = 0;//收回$i号,重新选择
		}
	}
}
$num = 0;
dfs(1,array(),array(),$num);

2、广度优先遍历

class Node{
    public $x;
    public $y;
    public $f;
    public $step;
}
        $queue = array();
        $num = 0;
        $next = array(
            0 => array(0,1),
            1 => array(1,0),
            2 => array(0,-1),
            3 => array(-1,0)
        );
        $migong = array(
            0 => array(0,0,1,0),
            1 => array(0,0,0,0),
            2 => array(0,0,1,0),
            3 => array(0,1,0,0),
            4 => array(0,0,0,1)
        );
        $start_x = 0;
        $start_y = 0;
        $step = 0;
        $destination_x = 3;
        $destination_y = 2;
        $p = new Node();
        $p->x = $start_x;
        $p->y = $start_y;
        $p->f = 0;
        $p->step = 0;
        $queue[] = $p;
        $book[$start_x][$start_y] = 1;
        $flag = 0;
        $head = 0;
        $tail = 1;
        //print_r($queue);
        while($head<$tail){
            for($k=0;$k<=3;$k++){
                $tx = $queue[$head]->x+$next[$k][0];
                $ty = $queue[$head]->y+$next[$k][1];
                //判断越界
                if($tx<0||$tx>4||$ty<0||$ty>3){
                    continue;
                }
                if($migong[$tx][$ty]==0&&(!isset($book[$tx][$ty])||$book[$tx][$ty]==0)){
                    print_r($tx.','.$ty.'<br>');
                    $book[$tx][$ty] = 1;
                    $q = new Node();
                    $q->x = $tx;
                    $q->y = $ty;
                    $q->f = $head;
                    $q->step = $queue[$head]->step+1;
                    $queue[$tail] = $q;
                    $tail++;
                    print_r($queue);
                }
                //到达目的地
                if($tx==$destination_x&&$ty==$destination_y){
                    $flag = 1;
                    print_r('什么鬼'.$tx.'=='.$ty);
                    break;
                }
            }
            if($flag==1)
                break;
            $head++;//当一个扩展结束后,head++才能对后面的点再进行扩展
            print_r('head:'.$head.'==tail:'.$tail.'<br>');
        } 
        //$this->bfs($start_x,$start_y,$destination_x,$destination_y,$step);
        print_r('step:'.$queue[$tail-1]->step);
        $index = $tail-1;
        $f_x = $queue[$index]->x;
        $f_y = $queue[$index]->y;
        while($f_x!==$start_x||$f_y!==$start_y){//打印路径
            print_r('('.$f_x.','.$f_y.')<br>');
            $index = $queue[$index]->f;
            $f_x = $queue[$index]->x;
            $f_y = $queue[$index]->y;
        }

3、最短路径算法
Floyd-Warshall算法基本思想:最开始只允许经过1号顶点进行中转,接下来只允许经过1号和2号顶点进行中转~~~允许经过1-n号所有顶点进行中转,求任意两点之间的最短路程,其实是一种动态规划的思想。

for($k=1;$k<m;$k++){
	for($i=1;$i<=m;$i++){
		for($j+1;$j<=m;$j++){
			if($e[$i][$j]>$e[$i][$k]+$e[$k][$j]){
				$e[$i][$j] = $e[$i][$k]+$e[$k][$j];
			}
		}
	}
}

单源最短路程算法(Dijkstra)基本思想:每次找到离源点最近的一个顶点,然后以该顶点为中心进行扩展,最终得到源点到其余所有点的最短路径。

基本步骤:
1、选一顶点v为源点,并视从源点v出发的所有边为到各顶点的最短路径(确定数据结构:因为求的是最短路径,所以①就要用一个记录从源点v到其它各顶点的路径长度数组dist[],开始时,dist是源点v到顶点i的直接边长度,即dist中记录的是邻接阵的第v行。②设一个用来记录从源点到其它顶点的路径数组path[],path中存放路径上第i个顶点的前驱顶点)。
2、在上述的最短路径dist[]中选一条最短的,并将其终点(即<v,k>)k加入到集合s中。
3、调整T中各顶点到源点v的最短路径。 因为当顶点k加入到集合s中后,源点v到T中剩余的其它顶点j就又增加了经过顶点k到达j的路径,这条路径可能要比源点v到j原来的最短的还要短。调整方法是比较dist[k]+g[k,j]与dist[j],取其中的较小者。
4、再选出一个到源点v路径长度最小的顶点k,从T中删去后加入S中,再回去到第三步,如此重复,直到集合S中的包含图G的所有顶点。

//核心算法
$inf = 99999;
for($i=1;$i<=n;$i++){
	$book[i] = 0;
	$dis[$i] = $e[1][$i];//1号顶点到其余各个顶点的初始路程
}
for($i=1;$i<=n-1;$i++){
	//找到离1号顶点最近的顶点
	$min = $inf;
	for($j=1;$j<=n;$j++){
		if($book[$j]==0 && $dis[$j]<$min){
			$min = $dis[$j];
			$u = $j;
		}
	}
	$book[$u] = 1;
	for($v=1;$v<=n;$v++){
		if($e[$u][$v]<$inf){
			if($dis[$v]>$dis[$u]+$e[$u][$v]){
				$dis[$v] = $dis[$u]+$e[$u][$v];
			}
		}
	}
}

Bellman-Ford算法(针对负权边):

for(k=1;k<=n-1;k++)//进行n-1轮松弛
	for(i=1;i<=m;i++)//枚举每一条边
		if(dis[v[i]] > dis[u[i]] + w[i])//尝试对每一条边进行松弛
			dis[v[i]] = dis[u[i]] + w[i];
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值