鉴于列表元组,我需要找到所有独特的路径:
Example I/P: [(1,2),(2,3),(3,4),(9,11),(4,5),(5,6),(6,7),(3,9)]
O/P: [[(1,2),(2,3),(3,4),(4,5),(5,6),(6,7)],[(1,2),(2,3),(3,9),(9,11)]]
如果元组的第二个元素与另一个元组的第一个元素匹配,则可以连接两个元组,即:一个元组是(_,a)
,其他元组就像(a,_)
。
最有效的实施方法是什么?我需要找到适合它的最佳数据结构。有什么建议 ?我将执行算法的元组数量将超过400,000。
答案 0 :(得分:3)
{-# LANGUAGE NoMonomorphismRestriction #-}
import Data.List (permutations, nub)
path :: Eq a => [(a, a)] -> [(a, a)]
path [] = []
path [x] = [x]
path (u@(_, a):v@(b, _):xs) = if a == b then u:path (v:xs) else [u]
allPaths = nub . map path . permutations
(您可以优化链生成,但我认为这个问题具有指数时间复杂度)
<强> EDITED 强>
通常,您必须更准确地定义要返回的路径。
忽略循环不变量([(1,2),(2,3),(3,1)] == [(2,3),(3,1),(1,3)])你可以生成所有路径(不使用排列)
{-# LANGUAGE NoMonomorphismRestriction #-}
import Data.List (permutations, nub, sortBy, isInfixOf)
data Tree a = Node a [Tree a] deriving Show
treeFromList :: Eq a => a -> [(a, a)] -> Tree a
treeFromList a [] = Node a []
treeFromList a xs = Node a $ map subTree $ filter ((a==).fst) xs
where subTree v@(_, b) = treeFromList b $ filter (v/=) xs
treesFromList :: Eq a => [(a, a)] -> [Tree a]
treesFromList xs = map (flip treeFromList xs) $ nub $ map fst xs ++ map snd xs
treeToList :: Tree a -> [[a]]
treeToList (Node a []) = [[a]]
treeToList (Node a xs) = [a:ws | ws <- concatMap treeToList xs]
treesToList :: [Tree a] -> [[a]]
treesToList = concatMap treeToList
uniqTrees :: Eq a => [[a]] -> [[a]]
uniqTrees = f . reverse . sortBy ((.length).compare.length)
where f [] = []
f (x:xs) = x: filter (not.flip isInfixOf x) (f xs)
allPaths = uniqTrees . treesToList . treesFromList
然后
*Main> allPaths [(1, 2), (1, 3), (2, 3), (2, 4), (3, 4), (4, 1)]
[[2,4,1,2,3,4],[2,3,4,1,2,4],[1,3,4,1,2,4],[1,3,4,1,2,3],[1,2,4,1,3,4],[1,2,3,4,1,3]]
uniqTrees
效率很低,一般来说,你可以做很多优化。
如果你想避免循环不变,你可以规范化选择最小base10表示的循环,在前面的例子中([(1,2),(2,3),(3,1)] == [(2, 3),(3,1),(1,3)])1231&lt; 2313然后
normalize [(2,3),(3,1),(1,3)] == [(1,2),(2,3),(3,1)]
你可以规范化一个旋转它n次的路径并取“head。sortBy toBase10.rotations”。
答案 1 :(得分:1)
我认为你的问题适用于NP类别,因为:
汉密尔顿路径,也称为汉密尔顿路径,是两条路径之间的路径 图的顶点,它只访问每个顶点一次。
一般来说,找到哈密顿路径的问题是NP完全的 (Garey and Johnson 1983,pp.199-200),所以唯一已知的方法 确定给定的一般图是否具有哈密顿路径 进行详尽的搜索(source)
你的问题甚至“更难”,因为你事先并不知道什么是结束节点。
就数据结构而言,您可以尝试在Haskell中模拟哈希表结构,因为此数据类型通常用于图表中,您可以将问题转换为图表。