【问题标题】:Collections sort method vs iteration集合排序方法与迭代
【发布时间】:2016-04-25 22:00:25
【问题描述】:

我正在研究一个纸牌洗牌问题,并找到了两种解决方案。

目标是将存储在数组中的所有 52 张扑克牌作为 Card 对象进行洗牌。 Card 类具有与之关联的 id 和 name。

现在,一种方法是使用 for 循环进行迭代,然后在临时卡对象持有者和随机数生成器的帮助下,我们可以交换两个对象。这种情况一直持续到我们达到一半的牌。

另一种方法是使用随机生成器编号实现可比较的重写 compareto 方法,因此每次调用该方法时都会得到随机响应。

你认为哪种方式更好?

【问题讨论】:

  • “所以我们每次调用该方法时都会得到一个随机响应。”不是这样 - 比较器需要在每次调用时保持一致,否则排序算法可能会抱怨,例如TimSort reports violation of general contract.
  • 已编辑。我会改用可比较的。
  • 这两种方法都比使用Collections.shuffle 更可取,它只是做正确的事。
  • @user2296988 不,实现Comparable 以返回随机排序有同样的问题。当您在实现Comparable 的集合上调用Collections.sort 时,它只是使用实现自然排序的比较器调用重载,即它将Comparator.compare 调用委托给Comparable.compareTo

标签: java


【解决方案1】:

您应该通过使用返回随机结果的比较器进行排序来做到这一点,因为这些随机结果可能彼此不一致(例如,说 athis demonstration by Mike Bostock。此外,它需要更长的时间,这对于 52 个对象的洗牌并不重要。

standard way to do it 确实涉及一个循环,但您的描述听起来很奇怪,我怀疑您的想法也可能不会产生理想的结果。 (如果更新问题以使“使用 for 循环迭代”方法的含义更清楚,我将更新此内容。)

一种通过排序获得良好改组的方法:将每个元素与一个随机数配对 - 例如,0..1范围内的随机浮点数 - 和然后使用该数字作为键进行排序。但这比 Fisher-Yates 慢并且需要额外的内存。在低级语言中,它通常也需要更多代码;在高级语言中它可能更简洁;我猜对于 Java它最终大致相等。)

[编辑添加:] 正如 Louis Wasserman 在 cmets 中非常明智地所说,当你的语言的标准库有一个现成的函数来做某事时,你通常应该使用它。除非您这样做是为了,例如,要求您找到并实施一种算法来解决问题的家庭作业。

【讨论】:

  • 你在 python 2 中的配对类似于map(lambda x, y: y, sorted(map(lambda x: (random(), x))) java stream api,或者任何好的函数式编程库都应该在 Java 中类似。
  • 是的,就是这样。你的观点是,在某些语言中它最终不会比 Fisher-Yates 更多的代码吗?好的,我同意并将相应地调整我的答案。 ...现在完成了。
【解决方案2】:

首先,您描述的比较器不起作用。更多关于这个here。 TLDR:比较必须是可重现的,所以如果你的比较器说a小于b,下次比较ba时,它应该返回“更大”,而不是随机的价值。 Comparable 也一样。

如果我是你,我宁愿使用Collections#shuffle method,它“使用默认随机源随机排列指定列表。所有排列发生的可能性大致相等”。依赖别人的代码总是更好,然后编写自己的代码,尤其是在标准库中时。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-12
    • 2018-10-25
    • 2014-03-31
    • 2010-12-10
    • 1970-01-01
    • 2013-01-11
    相关资源
    最近更新 更多