洗牌链表Java

时间:2012-07-11 23:50:34

标签: java random linked-list shuffle

我很难将伪代码用于混洗算法并将其转换为可用的java代码。我试图改组一个链表。总的来说,该方法采用链表头部的指针,并随机返回指向同一列表头部的指针。我想使用我创建的getLength和getItem方法。

public static ListElement shuffle(ListElement head){
  head = head.getLength();
  ListElement head2= null;
  while( head == null) {
    int random = (int) Math.random() *  n;
    for(int i=0;i<random;i++){
        head= head.getNext();
    }
  }
  return head;    
}

伪代码:

A list L of length n
A new list R, empty
while L is not empty
   pick a random k 
   such that 0<=k<= (length L)
   remove the kth element of L
      call it e
   prepend e to R

3 个答案:

答案 0 :(得分:0)

head = head.getLength();

看起来应该是int n = head.getLength();

while( head == null) {

看起来应该是while (head != null) {

int random = (int) Math.random() *  n;
for(int i=0;i<random;i++){
    head= head.getNext();

您正在覆盖head变量。您需要使用新变量来查找列表的第k个元素,并将头部指向旧列表。

一旦找到该元素,您就不会对该元素做任何事情,您需要从旧列表中提取它(硬)并将其添加到新列表中。

return head;

您需要返回新列表。

答案 1 :(得分:0)

我只是稍微重写一下代码,以便它遵循伪代码。

ListElement head2 = null;
int length = head.getLength();

while (head != null) {
    int k = (int) Math.random() * length;

    // Assume there is function deleteAt(index) that removes
    // the element at specified index and returns the deleted
    // element
    ListElement e = head.deleteAt(k);
    // Although I can just give the implementation - I'll leave this
    // as exercise.

    // You can have a function that add element to front
    // head2.addFront(e);
    e.setNext(head2);
    head2 = e;

    // Instead of querying the length again
    // decrement the length
    length--;
}
return head;

答案 2 :(得分:0)

您的伪代码的问题在于最糟糕的情况,每次您想要删除元素以将其添加到新列表时,您将不得不迭代到原始列表的末尾。

原始列表o = [a,b,c,d,e,f,g]
新列表:n = []

o = [a,b,c,d,e,f]
n = [g]

o = [a,b,c,d,e]
n = [g,f]

o = [a,b,c,d]
n = [g,f,e]

...

我现在能想到的最好的答案是创建一个列表大小的数组,并遍历原始链表,在随机位置插入数组:

原始列表o = [a,b,c,d,e,f,g]
新数组a = [,,,,,,]

o = [b,c,d,e,f,g]
a = [,, a ,,,,]

o = [c,d,e,f,g]
a = [,, a ,, b ,,]

o = [d,e,f,g]
a = [c ,, a ,, b ,,]

o = [e,f,g]
a = [c ,, a ,, b,d,]

...

将它们放入数组后,循环遍历数组并修复链接。

在原版中,您必须拨打getNext() 6次,然后拨打5次,然后拨打4次,再拨打3次...

在我的情况下,你打电话getNext() 6次,然后循环重置你的'下一个'参考数据。