当前位置: 首页 > news >正文

PHP图数据结构与算法实现

PHP图数据结构与算法实现

图是计算机科学中非常重要的数据结构。PHP虽然主要用于Web开发,但理解图算法对处理复杂关系数据很有帮助。今天说说常见的图算法在PHP中的实现。

图的表示方式有邻接矩阵和邻接表两种。邻接表在PHP中实现更自然。

```php
// 图的邻接表实现
class Graph
{
private array $adjacencyList = [];
private bool $directed;

public function __construct(bool $directed = false)
{
$this->directed = $directed;
}

public function addVertex(string $vertex): void
{
if (!isset($this->adjacencyList[$vertex])) {
$this->adjacencyList[$vertex] = [];
}
}

public function addEdge(string $from, string $to, int $weight = 1): void
{
$this->addVertex($from);
$this->addVertex($to);

$this->adjacencyList[$from][] = ['node' => $to, 'weight' => $weight];

if (!$this->directed) {
$this->adjacencyList[$to][] = ['node' => $from, 'weight' => $weight];
}
}

public function getVertices(): array
{
return array_keys($this->adjacencyList);
}

public function getNeighbors(string $vertex): array
{
return $this->adjacencyList[$vertex] ?? [];
}

// 广度优先搜索
public function bfs(string $start): array
{
$visited = [];
$queue = [$start];
$result = [];

while (!empty($queue)) {
$vertex = array_shift($queue);

if (isset($visited[$vertex])) continue;
$visited[$vertex] = true;
$result[] = $vertex;

foreach ($this->adjacencyList[$vertex] ?? [] as $neighbor) {
if (!isset($visited[$neighbor['node']])) {
$queue[] = $neighbor['node'];
}
}
}

return $result;
}

// 深度优先搜索
public function dfs(string $start): array
{
$visited = [];
$result = [];
$this->dfsRecursive($start, $visited, $result);
return $result;
}

private function dfsRecursive(string $vertex, array &$visited, array &$result): void
{
if (isset($visited[$vertex])) return;
$visited[$vertex] = true;
$result[] = $vertex;

foreach ($this->adjacencyList[$vertex] ?? [] as $neighbor) {
$this->dfsRecursive($neighbor['node'], $visited, $result);
}
}

// 拓扑排序
public function topologicalSort(): array
{
if (!$this->directed) {
throw new RuntimeException('拓扑排序只能用于有向图');
}

$inDegree = [];
foreach ($this->adjacencyList as $vertex => $neighbors) {
if (!isset($inDegree[$vertex])) $inDegree[$vertex] = 0;
foreach ($neighbors as $neighbor) {
$inDegree[$neighbor['node']] = ($inDegree[$neighbor['node']] ?? 0) + 1;
}
}

$queue = [];
foreach ($inDegree as $vertex => $degree) {
if ($degree === 0) {
$queue[] = $vertex;
}
}

$result = [];
while (!empty($queue)) {
$vertex = array_shift($queue);
$result[] = $vertex;

foreach ($this->adjacencyList[$vertex] ?? [] as $neighbor) {
$inDegree[$neighbor['node']]--;
if ($inDegree[$neighbor['node']] === 0) {
$queue[] = $neighbor['node'];
}
}
}

if (count($result) !== count($this->adjacencyList)) {
throw new RuntimeException('图中存在环,无法进行拓扑排序');
}

return $result;
}

// 最短路径(Dijkstra算法)
public function shortestPath(string $start, string $end): array
{
$distances = [];
$previous = [];
$unvisited = [];

foreach ($this->adjacencyList as $vertex => $neighbors) {
$distances[$vertex] = INF;
$previous[$vertex] = null;
$unvisited[$vertex] = true;
}
$distances[$start] = 0;

while (!empty($unvisited)) {
// 选取距离最小的未访问节点
$current = null;
$minDist = INF;
foreach ($unvisited as $vertex => $_) {
if ($distances[$vertex] < $minDist) {
$minDist = $distances[$vertex];
$current = $vertex;
}
}

if ($current === null || $current === $end) break;
unset($unvisited[$current]);

foreach ($this->adjacencyList[$current] ?? [] as $neighbor) {
$alt = $distances[$current] + $neighbor['weight'];
if ($alt < $distances[$neighbor['node']]) {
$distances[$neighbor['node']] = $alt;
$previous[$neighbor['node']] = $current;
}
}
}

// 重建路径
$path = [];
$current = $end;
while ($current !== null) {
array_unshift($path, $current);
$current = $previous[$current];
}

return [
'path' => $path,
'distance' => $distances[$end],
];
}
}

$graph = new Graph(true);

// 构建有向图
$graph->addEdge('A', 'B', 4);
$graph->addEdge('A', 'C', 2);
$graph->addEdge('B', 'C', 1);
$graph->addEdge('B', 'D', 5);
$graph->addEdge('C', 'D', 8);
$graph->addEdge('C', 'E', 10);
$graph->addEdge('D', 'E', 2);

echo "DFS: " . implode(' -> ', $graph->dfs('A')) . "\n";
echo "BFS: " . implode(' -> ', $graph->bfs('A')) . "\n";

$result = $graph->shortestPath('A', 'E');
echo "最短路径: " . implode(' -> ', $result['path']) . "\n";
echo "距离: {$result['distance']}\n";
?>
```

图算法在社交网络、路径规划、依赖管理等场景中很有用。PHP虽然不是做算法的最佳语言,但理解这些算法对日常开发中的复杂数据处理很有帮助。比如在分析用户关系、构建推荐系统或者处理任务依赖时,都能用到图算法的思想。

http://www.jsqmd.com/news/947313/

相关文章:

  • 工单响应时效从47分钟压缩至92秒,这3个AI集成节点你绝对漏掉了
  • 利用快马平台快速构建potplayer字幕翻译工具原型
  • 百度网盘限速终结者:3分钟搞定高速下载的终极方案
  • 合规红线下的智能外呼:如何用RAG+本地化语音模型通过银保监AI外呼备案(附过审配置清单)
  • 伺服驱动器方向反转排查与设置
  • Gemma 4 9B:面向开发者的轻量级AI生产力引擎
  • 动态多重网络层间差异检验:谱嵌入与Bootstrap方法
  • OpenCode 教程目录
  • Determined:一个集成的深度学习训练平台
  • 计算机重装系统出现SYSTEM磁盘?
  • 量子上三角矩阵代数UTq(n)的构造与Hopf结构解析
  • 高端音频旋转电位器怎么选?ALPS RK14J11R000H VS TONEVEE TV14 参数PK
  • 公平k中心聚类算法:原理、优化与应用
  • 基于深度学习的文本自动摘要系统
  • 推荐一个适合维保公司的报修系统,支持多报修单位独立管理
  • 第十章:最佳实践、完整配置模板与排障
  • 手机信号满格却上不了网?一文搞懂LTE/5G的PLMN选网与漫游机制
  • PHP域名解析与CDN加速技术
  • 告别选型内耗,大模型API 采购中转成为企业 AI 降本增效新支点
  • 避坑指南:STM32F103标准库DAC配置的那些“坑”与最佳实践
  • All-in-one数据底座的价值与实践:基于Harness的解读
  • 大模型能力演进:从版本幻觉到多模态原生表征
  • Gemma-2本地部署实战:手机电脑跑通2B大模型全指南
  • 利用快马内置git环境,三步完成项目原型创建与版本初始化
  • ZYNQ Linux下UIO中断配置踩坑记:从/dev下找不到uio设备到按键触发成功
  • Gemini 3.0实战指南:多模态理解与长上下文推理落地方法论
  • C#抽象类接口 项目实操选型清单(开发直接对照)
  • 开发2天,测试2个月:AI代码让谁偷懒了?
  • ARKFCM algorithm
  • 效率飙升:快马AI为你自动生成CentOS7运维管理效率工具包