OCaml在列表中插入一个元素

时间:2012-02-29 12:00:11

标签: algorithm list graph compression ocaml

将元素插入OCaml列表中特定位置的标准方法是什么。只允许递归。不允许任何分配操作。

我的目标是通过使用in_degree = out_degree = 1删除顶点来压缩ocaml中的图形。出于这个原因,我需要删除相邻的边缘以形成单个边缘。现在边缘在列表中[(6,7);(1,2);(2,3);(5,4)]。所以我需要从列表中删除这些边并添加一个边。 所以上面的列表现在看起来像[(6,7);(1,3);(5,4)]。在这里我们看到(1,2);(2,3)被移除并且(1,3)被插入第二位置。我为此设计了一种算法。但要做到这一点,我需要知道如何从位置2,3移除边(1,2);(2,3)并在位置2中插入(1,3)而没有任何显式变量并且以递归方式。

3 个答案:

答案 0 :(得分:5)

OCaml列表是不可变的,所以没有像在列表操作中删除和插入元素那样的东西。

您可以通过重复使用旧列表的某些部分来创建新列表。例如,要从(1, 3)::xs'创建列表(1, 2)::(2, 3)::xs',您实际上会重用xs'并使用cons构造函数创建新列表。

使用模式匹配非常方便:

let rec transform xs =                                             
  match xs with
  | [] | [_] -> xs
  | (x, y1)::(y2, z)::xs' when y1 = y2 -> (x, z)::transform xs'
  | (x, y1)::(y2, z)::xs' -> (x, y1)::transform ((y2, z)::xs')

答案 1 :(得分:4)

你可以这样做:

let rec compress l = match l with                                            
   [] -> []                                                           
 | x :: [] -> [x]                                                     
 | x1 :: x2 :: xs -> 
   if snd x1 = fst x2 then 
     (fst x1, snd x2) :: compress xs
   else x1 :: compress (x2 :: xs)

答案 2 :(得分:0)

您使用错误的数据结构来存储边缘,而您的问题并不表示您无法选择其他数据结构。正如其他海报已经说过的那样:列表是不可变的,因此重复删除其中的元素是一种相对昂贵的(O(n))操作。

我也不明白为什么你必须在第2位重新插入新边。图由G =(V,E)定义,其中V和E是顶点和边的。它们的顺序无关紧要。图的这个定义也已经告诉你边缘的更好的数据结构:集。

在ocaml中,集合由平衡二叉树表示,因此成员插入和删除的平均复杂度为O(log n)。所以你看到,为了删除成员,这种复杂性肯定比列表(O(n))更好,另一方面,将成员添加到集合中比使用缺点将元素添加到列表更昂贵操作

另一种数据结构是哈希表,其中插入和删除可以在O(1)时间内完成。让哈希表中的键成为你的边缘,因为你不使用这些值,只需使用像单位一样的常量或0。