美文网首页
一个图的遍历问题

一个图的遍历问题

作者: 鸿雁长飞光不度 | 来源:发表于2018-06-29 16:01 被阅读0次

设计数据库的存储形式存储帝都的地铁站信息,并求出从一个地点上车在不出站并且不重复的情况下最多能经过多少站,并把乘坐的站信息列出来。

很早以前在看书的时候里面有专门的章节介绍了图的遍历,当时里面的图的信息存储方式用的是二维数组。比如一共有5个点,数组大小是5*5,array[1][2] 的值如果不为规定的正无穷则表示这1和2两点之间不能直接连通,否则表示从点1到点2之间的距离为array[1][2],表示有向图的时候a[2][1]为正无穷,这样的表示非常直观,运算上也方便缺点是在图的顶点数比较多,但是连接数不多的时候会造成空间浪费,可以参考使用邻接表优化。

数据库中存储图的连接信息可以如下设计
id表示一条连通记录,from表示起始站的id,end表示终止点的id

      private $stations = [
        ['id' => 1, 'from' => 1, 'end' => 2],
        ['id' => 2, 'from' => 2, 'end' => 3],
        ['id' => 3, 'from' => 3, 'end' => 4],
        ['id' => 4, 'from' => 4, 'end' => 5],
        ['id' => 5, 'from' => 5, 'end' => 3],
        ['id' => 6, 'from' => 2, 'end' => 5],
        ['id' => 7, 'from' => 3, 'end' => 1],
        ['id' => 8, 'from' => 1, 'end' => 5],
    ];

可以将数据库的信息读取出来后再根据需要转换为二维数组或者邻接表的形式,也可以直接用。二维数组直接把起始点id和终止点id作为下标就能得到站点的连接信息,这里就是需要遍历而已。实现起来也很简单,就是图的深度优先遍历。

<?php
/*/**
 * Created by PhpStorm.
 * User: guodong
 * Date: 18/6/28
 * Time: 下午10:43
 */

class Station
{

    private $stations = [
//        ['id' => 1, 'from' => 1, 'end' => 2],
//        ['id' => 2, 'from' => 2, 'end' => 3],
//        ['id' => 3, 'from' => 3, 'end' => 4],
//        ['id' => 4, 'from' => 4, 'end' => 5],
//        ['id' => 5, 'from' => 5, 'end' => 3],
//        ['id' => 6, 'from' => 2, 'end' => 5],
//        ['id' => 7, 'from' => 3, 'end' => 1],
//        ['id' => 8, 'from' => 1, 'end' => 5],
        ['id' => 1, 'from' => 1, 'end' => 2],
        ['id' => 2, 'from' => 2, 'end' => 3],
        ['id' => 3, 'from' => 3, 'end' => 4],
        ['id' => 4, 'from' => 1, 'end' => 5],
        ['id' => 5, 'from' => 5, 'end' => 6],
        ['id' => 6, 'from' => 1, 'end' => 7],
        ['id' => 7, 'from' => 1, 'end' => 8],
        ['id' => 8, 'from' => 1, 'end' => 11],
        ['id' => 9, 'from' => 4, 'end' => 5],
    ];

    //深度优先搜索使用 getMaxStations
    public $visit = [];
    public $curMaxLength = 0;
    public $allRoutes = [];
    //广地优先搜索使用
    public $queue = [];
    public $book = [];

    //换成次数 leastTrans
    public $transTimes = 9999999;
    public $book2 = [];


    //求一点开始,在不出站的情况下可以不重复的坐最多多少站地铁,需要把所有的都存下来 (图的深度优先搜索遍历)
    //深度优先遍历
    function getMaxStations($startId = 5)
    {
        foreach ($this->stations as $station) {
            $flag = 0 ;
            if ($station['from'] == $startId && !isset($this->visit[$station['end']])) {
                $flag = 1;
                $this->visit[$station['end']] = 1;
                $this->getMaxStations($station['end']);
                unset($this->visit[$station['end']]);
            }
            if ($flag == 0) {
                $route = implode(",",array_keys($this->visit));
                if (!in_array($route, $this->allRoutes) && $route){
                    $this->allRoutes[] = $route;
                }
            }
        }
    }

    /*
     * 图的广度优先搜索
     */
    public function bfs($startId = 1)
    {
        array_push($this->queue, $startId);
        $this->book[] = $startId;
        //队列不为空
        while (!empty($this->queue)) {
            $startId = array_shift($this->queue);
            print $startId; //打印访问的节点
            foreach ($this->stations as $station) {
                if ($station['from'] == $startId && !in_array($station['end'], $this->book)) {
                    $this->book[] = $station['end'];
                    array_push($this->queue, $station['end']);
                }
            }

        }
    }

    /**
     * 求任意两点间的最少换成次数和细节
     * @param $startId
     * @param $endId
     */
    public function leastTrans($startId, $endId, $curTimes = 0)
    {

        //当前转战的次数大于已经记录的转战次数则放弃继续深度搜索
        if ($curTimes > $this->transTimes) {
            return;
        }
        if ($startId == $endId) {
            $this->transTimes = count($this->book2);
            print_r($this->book2);
        }
        //book2用来存储是否已经访问
        foreach ($this->stations as $station) {
            if ($station['from'] == $startId && !in_array($station['end'], $this->book2)) {
                array_push($this->book2, $station['end']);
                $this->leastTrans($station['end'], $endId, $curTimes + 1);
                array_pop($this->book2);

            }
        }
    }
}

$tool = new Station();
////
////$tool->leastTrans(1, 5);
////print_r($tool->transTimes);
//
$tool->getMaxStations(1);
print_r($tool->allRoutes);
$all = usort($tool->allRoutes,function ($val1,$val2){
   return strlen($val1) < strlen($val2);
});

print_r($tool->allRoutes);

相关文章

  • 一个图的遍历问题

    设计数据库的存储形式存储帝都的地铁站信息,并求出从一个地点上车在不出站并且不重复的情况下最多能经过多少站,并把乘坐...

  • 图的遍历——深度优先遍历问题

    从这道题来看,深度优先搜索遍历这个图:首先从没有走到过的顶点作为起始点,假如从1开始作为起始点,与1相连接的有顶点...

  • 两种图的遍历算法

    在给出图的定义后第一个问题就是如何遍历图的所有顶点,有两种最基础的图遍历算法。如果给图添加更多的特征和属性,将产生...

  • 图和遍历

    邻接矩阵定义一个图 其实就是二维数组来定义 图的遍历 深度搜索遍历 2.广度搜索遍历 遍历

  • 图的深度优先遍历

    数据结构遍历的意义 树的遍历 图的遍历 树的前序遍历 图遍历和树遍历区别 知识回顾 树的深度优先遍历 普通函数和递...

  • 图的理解:深度优先和广度优先遍历及其 Java 实现

    遍历 图的遍历,所谓遍历,即是对结点的访问。一个图有那么多个结点,如何遍历这些结点,需要特定策略,一般有两种访问策...

  • 搜索算法

    图的搜索(遍历) DFS 写法:递归或用 stack求解那种所有满足条件的路径的问题,很容易想到 DFS,而且遍历...

  • 深度优先遍历

    问题描述 按照给定的起始顶点深度优先遍历给定的无向图,尝试所有可能的遍历方式,打印遍历过程中出现的最大深度。 输入...

  • 图的深度优先遍历和马踏棋盘算法

    图的深度优先遍历思想 图的遍历通常有两种遍历次序方案: 深度优先遍历和广度优先遍历。深度优先遍历(DepthFir...

  • 图的DFS && BFS遍历

    对图的深度优先遍历: 对图的广度优先遍历:

网友评论

      本文标题:一个图的遍历问题

      本文链接:https://www.haomeiwen.com/subject/pruayftx.html