同样,这似乎应该是显而易见的事情。
我想在特定位置的链表中插入一个元素。
在一种情况下,这是元素中的字段小于某个值的位置,所以我可以这样做:
def Add(act:Elem):Unit = {
val (before, after) = myList.partition(elem.n >= _.n)
myList = (before :+ act) ++ after
}
...但这实际上是一种伪装成可变的方法。我不认为我可以到达与插入点对应的LinkedList节点,所以我不能搞乱“next”属性。
不应该这么困难。链接列表的一半是你在中间插入的东西。
我仍在使用编译器生成器(如this question中所述)。用副本替换列表并不是这样做的方法,因为有很多递归调用,在这些调用期间列表被故意修改,所以你可能会发现一些递归调用仍在使用你刚刚替换的列表。
我真的想要可变列表和简单易变的操作。我想我可以编写自己的集合类,但我认为不需要那么不寻常。任何人已经实施了“适当的”可交换链表?
修改
更多细节
我应该选择一个不同的例子。通常情况下,我通过其他路径获得了对元素的引用,并且我想在此元素所在的链接列表之一中插入一个新元素(我很高兴将元素放在一个链接列表中作为启动)
在我开始的朴素Java实现中,元素本身包含一个next
字段(然后我可以操作)。
在Scala LinkedList的情况下,链表节点包含对元素的引用,因此,给定元素,我不能轻易找到LinkedList节点,因此下一个字段。 我可以再次遍历列表,但可能会很长。
假设DoublyLinkedList并删除元素作为我想要的操作可能会有所帮助,因为它更清晰,因此不需要遍历,因此应该避免。所以在这种情况下,假设我通过其他方式找到了元素,而不是遍历链表。我现在想删除该元素。在Java / naive的情况下,后向和前向指针是元素的一部分。在Scala集合的情况下,有一个DoublyLinkedList节点,其中包含对我的元素的引用。但是,如果不再遍历列表,我就无法从元素转到该节点。
随机的想法如下:我通过混合定义下一个字段的Trait来获得某个地方(对于我单独链接的案例)。例如,该特征可能支持迭代列表中的对象。但这对我来说只有一次列在一个列表上的元素有帮助,而且我有三个对象(目前有三个不同的“下一个”指针称为“nezt”,“across”和“down”)
我不希望指向元素的节点列表,我想要一个节点元素列表(即有一个下一个字段)。
答案 0 :(得分:4)
不幸的是,LinkedList
没有实现Buffer
,因此没有AFAIK是开箱即用的好方法。实际上做可以访问next
字段,因此您可以自己编写。这样的事情(警告,未经测试!;警告,低级代码!):
def Add(act: Elem) {
var last = myList
while (last.next ne null && last.next.n >= act.n) last = last.next
var ins = LinkedList(act)
ins.next = last.next
last.next = ins
}
(您可能希望为myList
添加一个特殊情况为空,并在第一个元素之前插入。但是您明白了
澄清后编辑:不要保留元素的副本;保留从该元素开始的列表副本。 (那就是last
。)然后从你选择的东西列表到头部东西本身写一个隐式转换。除非你复制元素中的集合方法,否则你将获得集合库的所有功能以及具有下一个指针的元素的所有语法便利,只需要额外的对象分配作为缺陷。
当然,你可以随时实现你想要的任何低级数据结构,如果你想重新发明轮子以便它更适合你的车(可以这么说)。
答案 1 :(得分:2)
为什么人们会遇到这样的麻烦?
scala> LinkedList(1, 2, 3)
res21: scala.collection.mutable.LinkedList[Int] = LinkedList(1, 2, 3)
scala> val ll = LinkedList(1, 2, 3)
ll: scala.collection.mutable.LinkedList[Int] = LinkedList(1, 2, 3)
scala> ll.next.insert(LinkedList(0))
scala> ll
res23: scala.collection.mutable.LinkedList[Int] = LinkedList(1, 2, 0, 3)
scala> ll.insert(LinkedList(-1, -2))
scala> ll
res25: scala.collection.mutable.LinkedList[Int] = LinkedList(1, -1, -2, 2, 0, 3)
当然,在澄清之后,这并没有回答这个问题,但我认为Rex Kerr关于隐式转换的想法可能就是这里的方法。那个,或者只是在使用该值的任何方法之前添加.elem
。事实上,这是隐含的:
implicit def linkedListToA[A](ll: LinkedList[A]): A = ll.elem
答案 2 :(得分:1)
未修改版本:第一次谓词other
为真时,将l
插入p
。
import scala.collection.mutable.LinkedList
import scala.annotation.tailrec
val list = LinkedList(1, 2, 3, 10, 11, 12)
def insertAfter[T](l: LinkedList[T], other: LinkedList[T], p: (T) => Boolean) {
@tailrec
def loop(x: LinkedList[T]) {
if (p(x.head)) {
other.next = x.next
x.next = other
return
}
if (x.next.isEmpty) {}
else loop(x.next)
}
loop(l)
}
insertAfter(list, LinkedList(100), (_:Int) >= 10)