- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我试图用ocaml编写拓 flutter 排序,但是我是一个初学者(使用OCaml和图形算法),我自己无法做到。
对于我来说,考虑C++中的拓 flutter 排序比较容易(并且Internet上有很多C++中的拓 flutter 排序示例),但是我想学习一些新知识。此外,坦率地说,我发现了一些用OCaml编写的拓 flutter 排序示例,但我不理解它们。
假设我有一个列表(int * int list) list
,例如:myList = [(1, [2]); (5, [6; 7]); (3, [2]); (6, [3; 7]); (8, [7]); (4, [3; 1])];;
这意味着,我需要在任务1
之前“执行”任务2
,在任务4
和3
等之前“执行”任务1
。
我认为,该列表的输出应为:[8; 5; 6; 7; 4; 3; 1; 2]
(但是我不确定,因为我只是举了这个例子,所以如果我错了,请纠正我)
另外,我读过,拓 flutter 排序不适用于图的循环,因此循环必须有某种条件-当给定的图具有循环时,我们会引发异常(我认为这是一个好主意) 。
AFAIK,我需要在算法中使用DFS进行拓 flutter 排序,该DFS我不知道如何在OCaml中实现(我了解主要思想,但我不知道这在OCaml /函数式编程中如何工作)。
我非常感谢您的帮助,以帮助我理解这个概念(我的意思是拓 flutter 排序,OCaml /函数式编程中的DFS)。如果可以的话,如果您向我展示示例代码,那就太好了,因为(对我来说)阅读代码是理解算法概念的最佳方法。
我知道,对于您中的大多数人来说,这是一个简单的问题,但我希望,它不会阻止您帮助我。
PS:我正在独自学习OCaml(我正在读高中),所以我没有扎实的理论背景(无论是OCaml还是算法)。我已经开始学习OCaml,因为我想了解递归的概念,现在这种语言似乎很有趣,因为它确实与C++不同,因此我仍在尝试学习OCaml中的新知识。
最佳答案
首先,请注意,Objective Caml确实支持一种编程样式,尽管存在语法上的差异,但通过可变数据结构(引用,数组,哈希表)和命令式构造(for和while循环,变量赋值),它与C++非常相似。 。我在下面假设您实际上是在尝试按惯用的纯函数样式编写拓 flutter 排序。
纯粹的函数式编程主要是声明性的:应用于该值的此函数是此另一个值。这就是let x =
右侧是一个表达式(求值)而不是使用return
的一系列 Action 的原因。当然,改编通常描述为一系列步骤的算法时会出现麻烦。
幸运的是,有一种模式(实际上是一系列模式),可以通过将“更改X的值”变为“返回与旧对象相同的新对象”,以功能样式表示命令式算法。 X”的值。
传统的DFS算法涉及到逐步浏览图表,同时记住已经访问过哪些元素-通常(这样您就不会多次访问它们)并到达当前位置(以便您可以检测到周期)。因此,DFS算法的命令状态包括当前节点,访问节点集和当前路径中的节点集。所有这些数据都必须提供给递归调用,并且所有永久更改都必须由那些相同的递归调用返回。
从上面使用您的图结构,并结合两个集合的列表表示(这几乎不是最佳选择-Set
在这里是更好的选择),该算法看起来像这样:
let dfs graph start_node =
let rec explore path visited node =
if List.mem node path then raise (CycleFound path) else
if List.mem node visited then visited else
let new_path = node :: path in
let edges = List.assoc node graph in
let visited = List.fold_left (explore new_path) visited edges in
node :: visited
in explore [] [] start_node
new_path
的递归调用不会修改
explore
列表。这是功能数据结构比命令性结构更易于使用的情况的一个示例。
List.fold_left
的使用。当我们开始使状态显式时,我们用
-> unit
类型的显式函数替换了
-> state -> .. -> state
类型的隐式命令式函数(接受状态作为参数,返回新状态)。因此,命令式列表探索如下所示:
f edge_1 ; f edge_2 ; f edge_3
let state = f (f (f state edge_1) edge_2) edge_3)
List.fold_left f state [edge_1 ; edge_2 ; edge_3]
正是这样做的。吹着我自己的喇叭,但是我有
a nice article about this here。
element :: set
,因为这是一个返回新集合(列表)的操作,其中包含原始集合的所有元素与新元素。这将使原始集保持不变(这对于步骤1中所述的原因而言是不错的),同时使用恒定数量的内存(它会创建一个cons单元-一个简单的头尾对,其中包含对元素的引用和对集的引用):您不仅可以获得撤消功能,而且无需任何额外费用。
visited
中,在您的情况下,这些叶子代表应该最后完成的那些节点。简而言之,返回列表按拓 flutter 进行排序-但可能不包含所有元素,因为起点可能不是唯一的根元素(甚至根本不是根元素)。因此,这里涉及一个额外的处理步骤,包括从图中获取另一个节点,直到浏览完所有图为止。
let dfs graph visited start_node =
let rec explore path visited node =
if List.mem node path then raise (CycleFound path) else
if List.mem node visited then visited else
let new_path = node :: path in
let edges = List.assoc node graph in
let visited = List.fold_left (explore new_path) visited edges in
node :: visited
in explore [] visited start_node
let toposort graph =
List.fold_left (fun visited (node,_) -> dfs graph visited node) [] graph
dfs
的调用者指定已访问节点的列表。完全像以前一样,使用
List.fold_left
在从每个节点启动DFS时保留访问节点的列表。
exception CycleFound
... raise CycleFound ...
toposort
的类型恢复为更通用的
('a * ('a list)) list -> 'a list
。
module type NODE = sig
type t
end
module type Topo = functor (Node:NODE) -> struct
exception CycleFound of Node.t list
let dfs ...
let sort ...
end
Topo(Node).sort
的类型为
(Node.t * (Node.t list)) list -> Node.t list
,这意味着您可以通过定义具有该类型的节点模块来对所需的任何类型进行排序:
type recipe = Eggs | Milk | Wheat | Mix | Cook | Serve
module Node = struct
type t = recipe
end
let graph = [ Wheat, [Eggs,Milk,Mix] ;
Milk, [Mix] ;
Eggs, [Mix] ;
Mix, [Cook] ;
Cook, [Serve] ;
Serve, [] ]
module RecipeTopo = Topo(Node)
let sorted = RecipeTopo.sort graph
关于algorithm - OCaml中的拓扑排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4653914/
我在一本书(Interview Question)中读到这个问题,想在这里详细讨论这个问题。请点亮它。 问题如下:- 隐私和匿名化 马萨诸塞州集团保险委员会早在 1990 年代中期就有一个绝妙的主意
我最近接受了一次面试,面试官给了我一些伪代码并提出了相关问题。不幸的是,由于准备不足,我无法回答他的问题。由于时间关系,我无法向他请教该问题的解决方案。如果有人可以指导我并帮助我理解问题,以便我可以改
这是我的代码 public int getDist(Node root, int value) { if (root == null && value !=0) return
就效率而言,Strassen 算法应该停止递归并应用乘法的最佳交叉点是多少? 我知道这与具体的实现和硬件密切相关,但对于一般情况应该有某种指南或某人的一些实验结果。 在网上搜索了一下,问了一些他们认为
我想学习一些关于分布式算法的知识,所以我正在寻找任何书籍推荐。我对理论书籍更感兴趣,因为实现只是个人喜好问题(我可能会使用 erlang(或 c#))。但另一方面,我不想对算法进行原始的数学分析。只是
我想知道你们中有多少人实现了计算机科学的“ classical algorithms ”,例如 Dijkstra's algorithm或现实世界中的数据结构(例如二叉搜索树),而不是学术项目? 当有
我正在解决旧编程竞赛中的一些示例问题。在这个问题中,我们得到了我们有多少调酒师以及他们知道哪些食谱的信息。制作每杯鸡尾酒需要 1 分钟,我们需要使用所有调酒师计算是否可以在 5 分钟内完成订单。 解决
关闭。这个问题是opinion-based .它目前不接受答案。 想要改进这个问题? 更新问题,以便 editing this post 可以用事实和引用来回答它. 关闭 8 年前。 Improve
我开始学习 Nodejs,但我被困在中间的某个地方。我从 npm 安装了一个新库,它是 express -jwt ,它在运行后显示某种错误。附上代码和错误日志,请帮助我! const jwt = re
我有一个证书,其中签名算法显示“sha256rsa”,但指纹算法显示“sha1”。我的证书 SHA1/SHA2 的标识是什么? 谢谢! 最佳答案 TL;TR:签名和指纹是完全不同的东西。对于证书的强度
我目前在我的大学学习数据结构类(class),并且在之前的类(class)中做过一些算法分析,但这是我在之前的类(class)中遇到的最困难的部分。我们现在将在我的数据结构类(class)中学习算法分
有一个由 N 个 1x1 方格组成的区域,并且该区域的所有部分都是相连的(没有任何方格无法到达的方格)。 下面是一些面积的例子。 我想在这个区域中选择一些方块,并且两个相邻的方块不能一起选择(对角接触
我有一些多边形形状的点列表,我想将其包含在我页面上的 Google map 中。 我已经从原始数据中删除了尽可能多的不必要的多边形,现在我剩下大约 12 个,但它们非常详细以至于导致了问题。现在我的文
我目前正在实现 Marching Squares用于计算等高线曲线,我对此处提到的位移位的使用有疑问 Compose the 4 bits at the corners of the cell to
我正在尝试针对给定算法的约束满足问题实现此递归回溯函数: function BACKTRACKING-SEARCH(csp) returns solution/failure return R
是否有包含反函数的库? 作为项目的一部分,我目前正在研究测向算法。我正在使用巴特利特相关性。在 Bartlett 相关性中,我需要将已经是 3 次矩阵乘法(包括 Hermitian 转置)的分子除以作
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 这个问题似乎与 help center 中定义的范围内的编程无关。 . 关闭 8 年前。 Improve
问题的链接是UVA - 1394 : And There Was One . 朴素的算法是扫描整个数组并在每次迭代中标记第 k 个元素并在最后停止:这需要 O(n^2) 时间。 我搜索了一种替代算法并
COM 中创建 GUID 的函数 (CoCreateGUID) 使用“分散唯一性算法”,但我的问题是,它是什么? 谁能解释一下? 最佳答案 一种生成 ID 的方法,该 ID 具有一定的唯一性保证,而不
在做一个项目时我遇到了这个问题,我将在这个问题的实际领域之外重新措辞(我想我可以谈论烟花的口径和形状,但这会使理解更加复杂).我正在寻找一种(可能是近似的)算法来解决它。 我有 n 个不同大小的容器,
我是一名优秀的程序员,十分优秀!