我选择通过节点列表(例如n=[1,2,3,4]
)和表示边缘的对列表(例如m=[(1,2), (2,3)]
)来表示Haskell中的图形。现在我必须看看图表是否有很强的连接。
我的主要问题是如何查找图中2个节点之间是否有路径。我写了类似的东西:
-- sees if 2 nodes are adjacent
adjacent x y [] = False
adjacent x y (mu:m) =
if(x== (fst mu) && y==(snd mu)) then True
else adjacent x y m
-- the successor of a node, ex for the edge (1,2) the succ of 1 is 2
suc x [] = 0
suc x (l:list) =
if(x==(fst l)) then snd l
else suc x list
-- my main function
way 0 y list = False
way x y (mu:m)
| x==y = True
| (adjacent x y (mu:m)) == True = True
| otherwise =
if ((way (suc x (mu:m)) y (mu:m))==False) then way (suc x m) y m
else True
当我有1级节点时,它可以工作,但对于程度较大的节点,它并不总是有效。你能给我一些线索吗?
答案 0 :(得分:4)
以下是一些问题要问自己:
adjacent 3 2 [(1,2),(2,3)]
应该True
吗?1
[(1,2),(2,3),(1,4),(3,4)]
有多少后继者
way
为什么或不需要x==y
案例和adjacent x y ...
案件?way
的递归步骤中,== False
测试是否真的告诉您一些可以让您在m
的较小图表上进行递归的内容?通常,您尚未为顶级函数编写类型签名。这样做通常非常有启发性,并且会更清楚地传达您的设计:
type Vertex = Int
type Edge = (Vertex, Vertex)
type Graph = [Edge]
adjacent :: Vertex -> Vertex -> Graph -> Bool
suc :: Vertex -> Graph -> Vertex
way :: Vertex -> Vertex -> Graph -> Bool
考虑一下这些类型是否有意义,如果它们像您期望的那样分解您的问题,只需考虑一般的图形。
您的目标确实是way
功能,还是确定图表是否已连接?您可能会过多地假设您可以确定图表是否已连接。
最后,关于Haskell语法的一小部分:与大多数其他语言一样,函数应用程序绑定得非常紧密,比==
和&&
运算符更紧密。与大多数其他语言不同,函数应用程序不使用括号。因此,adjacent
可以重新编码为:
adjacent x y [] = False
adjacent x y (mu:m) =
if x == fst mu && y == snd mu then True
else adjacent x y m
反过来可以简化为:
adjacent x y [] = False
adjacent x y (mu:m) = (x == fst mu && y == snd mu) || adjacent x y m
答案 1 :(得分:3)
您有两个理解错误:
m
,您的边缘列表在整个搜索过程中都是静态的。请勿在{{1}}中重复使用它。way
是否具有any
到y。要查找邻居,首先必须way
边缘列表才能找到离开x的边缘。您还需要建立一个已经访问过的节点列表,以查找连接。如果您最终在已经看过的节点上,则该特定路径已失败。
一些提示可以缩短您的代码:对于filter
,请尝试adjacent
。
对于elem
,请尝试succ
和Data.Maybe.fromMaybe
。