将元素插入已排序的链表

时间:2019-02-09 17:25:03

标签: ocaml

我们必须实现insert函数,该函数可以将单元格插入排序的链表中。我的实现想法是要有两个rlist,分别称为previous和current,将用于遍历列表。在函数调用的开始,前一个rlist将包含一个随机整数,并且其下一个字段指向当前单元格,该单元格是linked_list的头部。我认为这是有问题的。我完成了我的想法。我认为该方法将在链接列表的正确位置添加正确的整数。但是,如果插入的元素在列表的开头,则当使用在屏幕上显示时,列表仍然是旧列表,但是旧列表确实确实有一个指向它的单元格,并且该单元格具有插入的整数。所以我不确定该如何处理。  我测试了我的方法,但它不如我所描述的那样起作用。 这是我做的事情:我在-9的末尾插入了-9。 c3确实在列表末尾得到-9。然后我在c5中添加了4。但是c5现在变成[5; 4; -9]。所以这是错误的,它应该改为[5; 4; 3; 2; 1; -9]。所以我不知道怎么了。

我在线上查找了如何实现该方法,以便他们可以给我一些启发或提示,但是他们提供的解决方案通常是Java或其他编程语言。

type cell = { data : int; next : rlist}
and rlist = cell option ref 

let c1 = {data = 1; next = ref None}
let c2 = {data = 2; next = ref (Some c1)}
let c3 = {data = 3; next = ref (Some c2)}
let c5 = {data = 5; next = ref (Some c3)} 

let rec displayList (c : rlist) =
  match !c with
  | None -> []
  | Some { data = d; next = l } -> d :: (displayList l) 

let cell2rlist (c : cell) :rlist = ref (Some c) 

let bigger((x:int), (y:int)) = (x > y) 



let insert (comp : (int * int) -> bool) (item : int) (listt :rlist)=
  let itemm = {data=item ; next = ref None} in
  let rec helper (prev : rlist) (item : cell) (current: rlist) funcc =
    match !current with
    |None -> (match !prev with 
        |Some w -> w.next := (Some itemm))
    |Some q -> if comp (item.data, q.data) then (itemm.next := (Some q) ; match !prev with 
      |Some w -> w.next := (Some itemm))
        else  prev := !current; current:= !(q.next); (helper prev item current funcc)
  in let previous = ref (Some {data=0; next = listt}) in
  helper previous itemm listt comp

以下是正在使用的代码的正确返回值的示例:

 let l5 = cell2rlist c5;;
val l5 : rlist = ....
(* Messy display deleted. *)



 displayList l5;;
- : int list = [5; 3; 2; 1]


 displayList l5;;
- : int list = [5; 3; 2; 1]


 insert bigger 4 l5;;
- : unit = ()


 displayList l5;;
- : int list = [5; 4; 3; 2; 1]


 insert bigger 9 l5;;
- : unit = ()


 displayList l5;;
- : int list = [9; 5; 4; 3; 2; 1]


 insert bigger 0 l5;;
- : unit = ()


 displayList l5;;
- : int list = [9; 5; 4; 3; 2; 1; 0]

但是当我运行代码时,这就是我得到的:

insert bigger 10 (ref(Some c5)) ;;
- : unit = ()

c5 ;;
- : cell =
{data = 5;
 next =
  {contents =
    Some
     {data = 3;
      next =
       {contents =
         Some
          {data = 2;
           next = {contents = Some {data = 1; next = {contents = None}}}}}}}}

如您所见,如果我在列表的开头插入了一个应该插入的数字,则看不到它。

这是另一个例子,

insert bigger 4 (ref(Some c5)) ;;
- : unit = ()

c5 ;;
- : cell =
{data = 5;
 next =
  {contents =
    Some
     {data = 4;
      next = {contents = Some {data = 1; next = {contents = None}}}}}}

因此,如您所见,该代码根本不起作用,因为更新后的列表应该具有值[5;4;3;2;1],而具有值[5;4;1]

这里是另一个示例:

insert bigger (-9) (ref(Some c3)) ;;
- : unit = ()

c3 ;;
- : cell =
{data = 3;
 next =
  {contents =
    Some
     {data = 2;
      next =
       {contents =
         Some
          {data = 1;
           next = {contents = Some {data = -9; next = {contents = None}}}}}}}}

因此,似乎该方法确实将元素正确插入到列表中,但是插入的单元格假定指向的列表似乎是错误的。

1 个答案:

答案 0 :(得分:1)

作为参考,这是一个显示代码失败的会话:

# let (l: rlist) = ref None;;
val l : rlist = {contents = None}
# insert bigger 1 l;;
- : unit = ()
# l;;
- : rlist = {contents = Some {data = 1; next = {contents = None}}}
# insert bigger 0 l;;
- : unit = ()
# l;;
- : rlist = {contents = None}

对于它的价值,如果代码正确缩进,那也很好。

无论如何,短时间查看您的代码时,我看到的是以下片段:

current:= !(q.next);
helper prev item current funcc

在我看来,您似乎在想,这里的第一行将前进一些局部变量,以指向列表的下一个元素。但是它实际上是在修改列表。

您可能想要更多类似这样的东西:

helper prev item q.next funcc

您的代码中还有其他问题。例如,then部分带有括号,而else部分却没有括号,这似乎很奇怪。