【问题标题】:Shuffling a linked list洗牌链表
【发布时间】:2015-06-30 23:05:57
【问题描述】:

我有一个本质上是伪库的类。驱动程序创建库 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);
      }
}

【问题讨论】:

  • 请在问题中输入代码(否则链接失效时问题将变得无用)
  • 请提供MCVE
  • “我不确定我哪里出错了。” - 没关系,我们不确定你在问什么,所以我们是平等的。跨度>
  • 让我重新措辞并尽量说清楚。很抱歉!
  • p1, p2, r1r2 应该在 for 循环内,swap 只是交换 p1p2 中的值,而不是它们指向的对象的内容。

标签: c++ linked-list


【解决方案1】:

非常接近,但是交换指针会打乱列表吗?对于洗牌,我们不需要以不同的方式链接节点吗?我们必须小心不要断开列表。

与其交换指针,不如交换它们的继任者?从随机性的角度来看,这同样好。这使得重新链接变得容易。

以下是一次交换洗牌迭代的示意图。

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 的价值是多少?我不确定,可能是列表长度的平方根。

【讨论】:

  • 首先,感谢您的回答。我很感激你的好意。其次,我正在努力跟进。 r1:2(比方说)和 r2:4 是什么意思?回头看看我的代码,我想更准确的说法是它实际上不是洗牌节点,而是随机交换节点之间的指针->bookVal 信息?
  • 不客气,我发现这个问题很有趣。希望答案对您有所帮助。响应: (1) 对于我的示例,我假设基于 rand() 的 r1 和 r2 值分别为 2 和 4。 (2) 在我回答时,问题的代码为swap(p1, p2);。您当前交换指向元素的代码,即swap(p1-&gt;bookVal, p2-&gt;bookVal); 最初,我担心交换任意大小的元素。然而,假设有效的元素交换实现,再想一想,我认为交换元素比指针重新链接更好。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-14
  • 1970-01-01
  • 2013-10-26
  • 2018-01-30
相关资源
最近更新 更多