我有一个基本上是伪库的类。驱动程序创建可以执行不同操作的库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);
}
}
答案 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
的好价值?我不确定,也许是列表长度的平方根。