当前位置: 首页 > 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.gsyq.cn/news/1458825.html

相关文章:

  • Gemma 4 9B:面向开发者的轻量级AI生产力引擎
  • 动态多重网络层间差异检验:谱嵌入与Bootstrap方法
  • OpenCode 教程目录
  • 量子上三角矩阵代数UTq(n)的构造与Hopf结构解析
  • 公平k中心聚类算法:原理、优化与应用
  • 大模型能力演进:从版本幻觉到多模态原生表征
  • 避坑指南:STM32F103标准库DAC配置的那些“坑”与最佳实践
  • 利用快马内置git环境,三步完成项目原型创建与版本初始化
  • Gemini 3.0实战指南:多模态理解与长上下文推理落地方法论
  • 开发2天,测试2个月:AI代码让谁偷懒了?
  • ZYNQ Linux下UIO中断配置踩坑记:从/dev下找不到uio设备到按键触发成功
  • 效率飙升:快马AI为你自动生成CentOS7运维管理效率工具包
  • 手机号定位查询系统:3秒获取号码归属地与地理位置
  • 避坑指南:STM32 HAL库下TM1640时序调试的那些事儿(基于SysTick和定时器两种延时)
  • 十年教学经验总结:新手小提琴怎么选?全价位高口碑机型实测推荐
  • 别再让EMC测试卡脖子!硬件工程师必看的电磁兼容设计实战避坑指南
  • 大语言模型越狱攻击:原理、挑战与防御策略
  • 实战cnn项目:基于快马ai生成从数据加载到模型可视化的猫狗分类完整代码
  • 第一章:OpenCode 项目概览与核心定位
  • 2026论文降AI率平台:11款工具实测谁在“智能”谁在“智障”?
  • 效率倍增:基于快马生成openclaw可参数化的一键部署与配置模板
  • 效率提升:借助快马AI批量生成头歌算法题解与优化方案
  • 拆解Transformer本源:350行源码吃透Attention底层原理
  • MATLAB零基础用Excel点坐标秒出圆心和半径,不装工具箱也能跑
  • 用快马ai三分钟搭建数据库管理工具原型,告别navicat激活烦恼
  • 杭州千岛泵业有限公司2026泵体设备十强精选:水喷射真空机组哪家好/优质机组生产厂家推荐杭州千岛泵业 - 栗子测评
  • 2026论文隐藏级降AIGC工具大曝光:一键压到安全线谁最稳
  • 利用快马平台快速构建autosar基础软件模块演示原型
  • 2026年AI编程工具深度评测与推荐榜单
  • 长春市2026年最新黄金回收白银回收铂金回收门店排行榜+联系方式电话推荐 - 大熊猫898989