洗牌链接列表

时间:2015-04-23 01:30:00

标签: c++ linked-list

我有一个基本上是伪库的类。驱动程序创建可以执行不同操作的库NoviceLibrary,例如向库中添加书籍(链接列表ListNode的节点),删除书籍等等。

shuffleBooks()是我必须编写的最后一个函数。其他一切都有效,可以添加/删除书籍。此函数需要以随机顺序将节点放在链表中。我不能使用尾部指针,我已经在其他算法中看到了。我无法使用数组。我以为我写的是有指针p1和p2交换列表中的节点。该程序停滞不前,并没有在日志中提供有用的信息。

void shuffleBooks (int bookCount)
{
      int r1 = rand() % bookCount;
      int r2 = rand() % bookCount;

      ListNode *p1 = head;
      ListNode *p2 = head;

      // Here I am trying to get the swap to happen 4 times the bookCount
      for (int i = 0; i < bookCount*4; i++)
      {
         for (int i = 0; i < r1; i++)
            p1 = p1->next;

         for (int i = 0; i < r2; i++)
            p2 = p2->next;

         swap(p1->bookVal, p2->bookVal);
      }
}

1 个答案:

答案 0 :(得分:0)

非常接近,但正在交换列表中的指针?为了改组,我们不需要以不同方式链接节点吗?我们必须小心,我们不要断开列表。

而不是交换指针,如何交换他们的后继者?从随机性的角度来看,这同样是好的。这使得重新链接变得容易。

以下是swap-shuffle的一次迭代的示意图。

list: A -> B -> C -> D -> E -> F -> G -> H
r1: 2 (say)
r2: 4 (say)
p1: C
p2: F

swap p1->next (D) and p2->next (G)

  // save pointers
  p1next = p1->next;         // D
  p1nextnext = p1next->next; // E
  p2next = p2->next;         // G
  p2nextnext = p2next->next; // H

  // relink
  p1->next = p2next;         // C -> G
  p2next->next = p1nextnext; // G -> E
  p2->next = p1next;         // F -> D
  p1next->next = p2nextnext; // D -> H

list: A -> B -> C -> G -> E -> F -> D -> H

Real code need to be careful not to dereference a null pointer.

我们可以执行上述步骤k次以获得良好的洗牌。什么是k的好价值?我不确定,也许是列表长度的平方根。