本文目录导读:

在PHP项目中实现最短路径算法,通常有以下几种常见方案,取决于你的具体需求:
核心算法实现
Dijkstra算法(单源最短路径)
适用于非负权值图,是最常用的算法:
class Dijkstra {
private $graph;
public function __construct($graph) {
$this->graph = $graph;
}
public function shortestPath($source, $target) {
$distances = [];
$previous = [];
$unvisited = [];
// 初始化
foreach ($this->graph as $vertex => $neighbors) {
$distances[$vertex] = INF;
$previous[$vertex] = null;
$unvisited[$vertex] = true;
}
$distances[$source] = 0;
while (!empty($unvisited)) {
// 找到未访问中距离最小的顶点
$minVertex = null;
foreach ($unvisited as $vertex => $value) {
if ($minVertex === null || $distances[$vertex] < $distances[$minVertex]) {
$minVertex = $vertex;
}
}
if ($minVertex === $target) {
break;
}
unset($unvisited[$minVertex]);
// 更新邻居距离
foreach ($this->graph[$minVertex] as $neighbor => $weight) {
$alternative = $distances[$minVertex] + $weight;
if ($alternative < $distances[$neighbor]) {
$distances[$neighbor] = $alternative;
$previous[$neighbor] = $minVertex;
}
}
}
// 重构路径
$path = [];
$current = $target;
while ($current !== null) {
array_unshift($path, $current);
$current = $previous[$current];
}
return [
'distance' => $distances[$target],
'path' => $path
];
}
}
// 使用示例
$graph = [
'A' => ['B' => 4, 'C' => 2],
'B' => ['D' => 5, 'C' => 1],
'C' => ['D' => 8, 'E' => 10],
'D' => ['E' => 2],
'E' => []
];
$dijkstra = new Dijkstra($graph);
$result = $dijkstra->shortestPath('A', 'E');
print_r($result);
Bellman-Ford算法(支持负权值)
class BellmanFord {
public function shortestPath($graph, $source, $target) {
$vertices = array_keys($graph);
$distances = [];
$previous = [];
// 初始化
foreach ($vertices as $vertex) {
$distances[$vertex] = INF;
$previous[$vertex] = null;
}
$distances[$source] = 0;
// 松弛所有边 |V|-1 次
for ($i = 0; $i < count($vertices) - 1; $i++) {
foreach ($graph as $u => $neighbors) {
foreach ($neighbors as $v => $weight) {
if ($distances[$u] + $weight < $distances[$v]) {
$distances[$v] = $distances[$u] + $weight;
$previous[$v] = $u;
}
}
}
}
// 检查负权环
foreach ($graph as $u => $neighbors) {
foreach ($neighbors as $v => $weight) {
if ($distances[$u] + $weight < $distances[$v]) {
return ['error' => '图中包含负权环'];
}
}
}
// 重构路径
$path = [];
$current = $target;
while ($current !== null) {
array_unshift($path, $current);
$current = $previous[$current];
}
return [
'distance' => $distances[$target],
'path' => $path
];
}
}
数据库存储方案
邻接表存储结构
CREATE TABLE nodes (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(100) NOT NULL
);
CREATE TABLE edges (
id INT PRIMARY KEY AUTO_INCREMENT,
from_node INT,
to_node INT,
weight DECIMAL(10,2),
FOREIGN KEY (from_node) REFERENCES nodes(id),
FOREIGN KEY (to_node) REFERENCES nodes(id),
INDEX idx_from (from_node),
INDEX idx_to (to_node)
);
PHP实现数据库查询
class GraphDatabase {
private $pdo;
public function __construct($pdo) {
$this->pdo = $pdo;
}
public function loadGraph() {
$stmt = $this->pdo->query("
SELECT n1.name as from_name, n2.name as to_name, e.weight
FROM edges e
JOIN nodes n1 ON e.from_node = n1.id
JOIN nodes n2 ON e.to_node = n2.id
");
$graph = [];
while ($row = $stmt->fetch()) {
$graph[$row['from_name']][$row['to_name']] = $row['weight'];
}
return $graph;
}
}
实用扩展方案
A*算法(带启发式搜索)
适用于大规模地图,比Dijkstra更高效:
class AStar {
private $graph;
public function shortestPath($start, $goal, $heuristicCallback) {
$openSet = [$start];
$cameFrom = [];
$gScore = [$start => 0];
$fScore = [$start => $heuristicCallback($start, $goal)];
while (!empty($openSet)) {
// 找到fScore最小的节点
$current = array_reduce($openSet, function($a, $b) use ($fScore) {
return $fScore[$a] < $fScore[$b] ? $a : $b;
});
if ($current === $goal) {
return $this->reconstructPath($cameFrom, $current);
}
$openSet = array_diff($openSet, [$current]);
foreach ($this->graph[$current] as $neighbor => $weight) {
$tentativeGScore = $gScore[$current] + $weight;
if (!isset($gScore[$neighbor]) || $tentativeGScore < $gScore[$neighbor]) {
$cameFrom[$neighbor] = $current;
$gScore[$neighbor] = $tentativeGScore;
$fScore[$neighbor] = $gScore[$neighbor] + $heuristicCallback($neighbor, $goal);
if (!in_array($neighbor, $openSet)) {
$openSet[] = $neighbor;
}
}
}
}
return null; // 无路径
}
private function reconstructPath($cameFrom, $current) {
$path = [$current];
while (isset($cameFrom[$current])) {
$current = $cameFrom[$current];
array_unshift($path, $current);
}
return $path;
}
}
性能优化建议
-
使用优先队列:用SplPriorityQueue替代数组查找
$queue = new SplPriorityQueue(); $queue->setExtractFlags(SplPriorityQueue::EXTR_BOTH);
-
缓存中间结果:对于地图应用,缓存常用路径
$cache = new Redis(); $cacheKey = "path_{$from}_{$to}"; if ($cached = $cache->get($cacheKey)) { return unserialize($cached); } -
分治处理:大型图考虑分区计算
// 将地图分成多个区域,先计算区域间路径
实际应用场景
- 物流配送系统:使用Dijkstra + 实时交通数据
- 社交网络:使用BFS(无权图)
- 导航系统:A*算法 + 地理坐标启发函数
- 网络路由:Bellman-Ford或SPFA
选择哪种方案取决于你的具体需求:数据量大小、是否支持负权、是否需要实时计算、内存限制等,对于大多数PHP Web应用,Dijkstra算法配合数据库存储是最实用的选择。
版权声明:足球直播
足球直播
足球直播
足球直播
足球直播
中超直播
中超直播
中超直播
中超直播
中超直播
英超直播
英超直播
英超直播
英超直播
英超直播
德甲直播
德甲直播
德甲直播
德甲直播
德甲直播
西甲直播
西甲直播
西甲直播
西甲直播
西甲直播
意甲直播
意甲直播
意甲直播
意甲直播
意甲直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
足球直播
足球直播
足球直播
足球直播
足球直播
中超直播
中超直播
中超直播
中超直播
中超直播
英超直播
英超直播
英超直播
英超直播
英超直播
德甲直播
德甲直播
德甲直播
德甲直播
德甲直播
西甲直播
西甲直播
西甲直播
西甲直播
西甲直播
意甲直播
意甲直播
意甲直播
意甲直播
意甲直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
足球直播
足球直播
足球直播
足球直播
足球直播
中超直播
中超直播
中超直播
中超直播
中超直播
英超直播
英超直播
英超直播
英超直播
英超直播
德甲直播
德甲直播
德甲直播
德甲直播
德甲直播
西甲直播
西甲直播
西甲直播
西甲直播
西甲直播
意甲直播
意甲直播
意甲直播
意甲直播
意甲直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播