Java 洗牌链表

Java 洗牌链表,java,random,linked-list,shuffle,Java,Random,Linked List,Shuffle,我很难为洗牌算法使用伪代码,并将其转换为可工作的java代码。我正在尝试洗牌一个链接列表。总的来说,该方法获取链表头的指针,并随机返回指向同一列表头的指针。我想使用我创建的getLength和getItem方法 public static ListElement shuffle(ListElement head){ head = head.getLength(); ListElement head2= null; while( head == null) { int rand

我很难为洗牌算法使用伪代码,并将其转换为可工作的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;    
}
公共静态ListElement洗牌(ListElement头){
head=head.getLength();
ListElement头2=null;
while(head==null){
int random=(int)Math.random()*n;
对于(int i=0;i
看起来应该是
int n=head.getLength();

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


您需要返回新列表。

我只是稍微重写了代码,使其遵循伪代码

return head;
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;

伪代码的问题是,在最坏的情况下,每次要删除元素以将其添加到新列表时,都必须迭代到原始列表的末尾

return head;
原始列表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次,然后在数组中循环重置“下一个”引用。

ListElement是什么?你能发布代码吗?@Sujay:我很确定它是链接列表。是的ListElement是链接列表。你的代码是剪切粘贴的吗?head被视为一个元素和一个长度。“n”被使用,但没有定义。你的伪代码看起来不错-rem余烬当您从L中删除项目时,L的长度会发生变化。我想学习如何使用math.random()这就是为什么我在集合中使用它而不是洗牌。随机数生成器可能会多次返回相同的索引值,特别是对于小列表。这意味着在您的情况下,您可以用迭代的成本来换取生成比严格要求更多的随机数的成本。。。(此外,还需要过滤掉这些值。)如果取了点,只取最近的打开点。发生冲突还有另一个问题——RNG可能多次生成相同的值,因此您需要将其过滤掉。@user268396这不是真正的随机移动。您需要在移动时从列表中删除元素,以便只从其余元素中随机选择。
int random = (int) Math.random() *  n;
for(int i=0;i<random;i++){
    head= head.getNext();
return head;
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;