]> git.andy128k.dev Git - missing-tools.git/commitdiff
topological sort algorithm
authorAndrey Kutejko <andy128k@gmail.com>
Sun, 9 Nov 2014 08:28:31 +0000 (10:28 +0200)
committerAndrey Kutejko <andy128k@gmail.com>
Sun, 9 Nov 2014 08:28:31 +0000 (10:28 +0200)
src/algorithm.php [new file with mode: 0644]

diff --git a/src/algorithm.php b/src/algorithm.php
new file mode 100644 (file)
index 0000000..9873e67
--- /dev/null
@@ -0,0 +1,56 @@
+<?php
+
+namespace PFF;
+
+class TopSort
+{
+    private $following, $visited = array(), $result = array();
+
+    private function getFollowing($obj)
+    {
+        return call_user_func($this->following, $obj);
+    }
+
+    private function once($obj)
+    {
+        if (in_array($obj, $this->visited)) {
+            return false;
+        } else {
+            $this->visited[] = $obj;
+            return true;
+        }
+    }
+
+    private function visit($obj, $chain)
+    {
+        if (in_array($obj, $chain)) {
+            $chain[] = $obj;
+            return $chain;
+        }
+
+        if ($this->once($obj)) {
+            $chain[] = $obj;
+            foreach ($this->getFollowing($obj) as $following) {
+                $loop = $this->visit($following, $chain);
+                if ($loop !== false)
+                    return $loop;
+            }
+            $this->result[] = $obj;
+        }
+        return false;
+    }
+
+    public static function sort($initialNodes, $following)
+    {
+        $sort = new self;
+        $sort->following = $following;
+
+        foreach ($initialNodes as $start) {
+            $loop = $sort->visit($start, array());
+            if ($loop !== false)
+                return array(false, $loop);
+        }
+        return array(true, $sort->result);
+    }
+}
+