高效排序实际纸牌的方法

23

我经常需要整理一些卡牌。这些是编号为1到216的“收藏家”卡牌,其中有重复和缺失的数字。

我正在寻找适用于物理卡牌的排序算法。插入排序似乎很好,因为插入卡牌不需要像在计算机内存中那样移动后续的卡牌。然而,浏览大量卡牌耗时。对于大堆卡牌,甚至有可能掉落卡牌,并且必须重新开始排序。

我可以在一个大桌子上画出卡牌,并直接将每张卡牌放到其正确的位置,但这需要相当大的空间,而且不是非常方便。

我的常规方法是首先浏览整个卡牌堆,并将它们放入1-49、50-99、100-149、150-199、200+的堆栈中。然后我扫描每个堆栈,并将它们放入0、1、2、3、4的堆栈中。最后,我对每个10个卡牌组合应用插入排序。尽管如此,这仍然是一个繁琐的过程。

另一个想法是将50个堆栈粗略地排序。25个将围绕中间,40个将在堆栈的末尾附近等等。这很快就可以带来一个大致排序的50卡牌堆,我可以轻松浏览并修复排序。

我想知道是否有更复杂的算法可以方便地应用于物理卡牌。我不知道怎么使用快速排序,类似堆排序的算法需要知道卡牌在卡牌堆中的索引。


有趣的问题,但并不是真正的编程问题 - 是否有其他适合发布此类问题的StackExchange网站? - Dan Puzey
1
“1到200多” - 实际的上限是多少?牌的大小有多大,是普通的扑克牌大小吗? - AakashM
如果限制确实是200,那么你浪费时间担心复杂的排序,可以把注意力放在其他事情上。 - Scott Evernden
7个回答

9
我认为快速排序是最简单的方法。我认为甚至有一些YouTube视频展示了人们如何使用普通扑克牌进行此操作。
您需要浏览整个牌组并将所有小于100的卡片放在左边,将所有大于100的卡片放在右边。然后您可以通过深度优先递归遍历这些堆栈(以便您不会同时拥有太多堆栈)。在某个阈值(可能约为5张卡片)时,您只需“手动”排序(类似于插入排序)。最后,您将这些堆栈叠在一起。
您还可以执行合并排序:将牌堆分成两个,深度优先递归,直到到达每个堆栈的5张卡片。将这两个堆栈“手动”排序,然后将它们面朝上并排放置。通过始终将显示卡片中较低的那张卡片放在结果堆栈上来将它们合并成一个结果堆栈。通过使已排序的堆栈保持面朝上来查看哪些堆栈已经排序。确保始终合并大小相似的堆栈,否则请继续拆分下一个未排序的堆栈。
编辑:基数排序也可能很好:按其最后一位将卡片放入十个堆栈中,按顺序将这些堆栈叠在一起。然后,按其倒数第二位将卡片放入十个堆栈中,再次按顺序将它们堆叠在一起。最后,按其倒数第三位(根据您的说明,这是第一位)将它们放入堆栈中,并将这些堆栈堆叠在一起,完成。毕竟,这可能是最简单的方法,并且它是O(n)(您需要通过整个牌组进行三次遍历)。

2
我喜欢基数排序。你需要把卡牌面朝下放在堆上,否则它就无法排序。快速排序也很好,有时候,你可以猜到比/2更好的枢轴。在我看来,比基数排序要繁琐一些。 - Eric Darchis

4
我曾经教授过一些学生众多的大学课程,并且我有处理分级考试的类似任务的经验。我几乎总是使用桶排序,就像你一样。你还提到了归并排序方法,我有时也会使用它,但只有在你从已排序的子文件开始而不是从完全混乱的卡片集开始时才能节省时间。
有一些技巧可以加快桶排序的速度。人工桶排序中大部分时间都花费在计算下一个项目的桶中,你可以尝试两种技巧。首先,你可以按数字进行桶排序,我想这被称为基数排序,这样你就不必比较数字了。 第一阶段使用三个桶,这并不是很多,但可能还可以。第二阶段是“主要”的工作,有十个桶。在第三阶段,你正在对十张编号的卡片进行排序,常识表明应该使用插入排序。但即使在那个阶段,基数排序也可以加快速度,即使每个桶只有一张卡片。当然,你不应该使用四面桶,而只应该在桌子上放置一堆卡片。如果很容易以顺序拾起卡片,则只需在个位数上使用桶法。也许对于中间阶段来说,一个有三面的插槽比放一堆卡牌更好。
第二个技巧是将桌子上的位置标记为0到9,以便你可以更快地找到正确的堆。标签可以粘贴在桌子上,以便重复使用。
我不确定这种特定的桶排序策略是否是最好的。重点是桶排序是对期中考试进行排序的最常用方法,并且对于大型卡片组也可能是最佳选择。有几种变化可以尝试,你应该尝试一下并找出哪种方法最有效。

此外,尽管AakashM的回答,我建议使用一种让你尽可能少思考的算法。它不仅慢,而且如果我必须集中注意力,我的大脑会感到疲劳,我会开始犯错误。 - Greg Kuperberg

3

Eric,

不确定你是否仍然需要订购实体纸牌,但我正在研究这个(卡片排序、针对排序、排序机等),并偶然看到了您的帖子。如果您不需要,那么希望其他人可能会发现它有用/有帮助。

如果您有使用打孔器并修改卡牌堆边缘的能力,则可以使用一种排序技术在log2(#of cards)操作中对整个牌堆进行排序。因此,大约需要8次操作才能完成200张卡牌的排序。

我发现有效的一种方法如下:

1.)按照您想要的方式对牌堆进行排序,并为每张卡片编号。

2.)将此号码转换为二进制,长度为log2(# of cards)。 例如log2(216)〜8,则只需要8个位置...因此0x0将变为00000000

3.)像下面的图片一样使用它的二进制表示对每张卡牌进行编码

Cards pic

4.)像下面的卡片1那样修剪掉1的部分(右侧或LSB)。卡片2上的倒数第二张卡片也被修剪掉...

5.)拿一根钉子、编织针或直挺的衣架等...将牌堆(无序)压在一起,孔都对齐

6.)将针插入整个牌堆的右手孔(或二进制中的LSB)。抬起针头,让没有戒指的标签(您剪掉它)的卡落入盒子中。将钩住的卡片移动到牌堆的前面。 **在取出所选卡片时,不要改变未选择卡片的顺序....例如保持牌盒松散适合的卡片盒或类似物品中的牌堆

7.)再次将牌堆压在一起,这次使用先前使用过的相邻孔上的针(右侧第二个孔)。做同样的事情,让未连接/未选择的卡片落入盒子并重复。

8.)进行8次操作,整个牌堆应该已经排序...希望这可以帮助某些人

以下是其工作原理: 第一步操作(步骤6)将所有奇数整数移到前面,例如将1放在2前面,3放在4前面等等。

第二步操作将(1/2)移到(3/4)前面,将(5/6)移到(7/8)前面。 第三步操作将(1/2/3/4)移到(5/6/7/8)前面,将(9/10/11/12)移到(13/14/15/16)前面。 第四步操作将(1/2/3/4/5/6/7/8)移到(9/10/11/12/13/14/15/16)前面。 最后的操作将大约一半的牌堆放在另一半前面,并以最少的步骤得到完全有序的牌堆。
祝好, Jeremy

2
我询问实际总数和大小的原因是,如果所有可能牌的总面积足够小,那么可能只需要将整个牌堆按正确位置放入网格中,然后按顺序拿起它们。例如,如果最多有100张牌,编号从1到100,则可以将工作表面分成一个10 x 10的矩形网格;然后在处理每张牌时,将67号卡片放在第6行第7列的位置。一旦所有卡片都铺好了,就按顺序拿起它们。这仅适用于您的工作表面足够大以容纳所有卡片的情况,但如果它们是普通的纸牌大小并且您有一个漂亮的大桌子,应该能够处理您提到的200张牌,特别是因为您可以轻松重叠“单元格”,并且该方法仍然有效。对我来说,这是最充分利用这是一个物理空间问题的方法,而不是bit位问题 - 每个物理对象仅被处理两次(一次放置,一次拿起),因为对于涉及物理对象的算法,“移动它们”的成本比“思考该怎么做”要高得多。

1
如果你在分类大象的话,我会同意。但是在分类考试方面,我的经验并非如此。 - Greg Kuperberg

1
我看到这篇文章是因为我想快速排序一副普通的52张纸牌。一些尝试表明,使用每个花色为一堆,然后逐个花色进行插入排序的算法,我可以在大约1:30内将整副牌排序完成(几乎没有练习,所以我相信通过练习可以更快地完成)。
我尝试了几种不同的方法,包括进行红黑分裂,然后将红色和黑色分别分成自己的花色,然后逐个花色进行插入排序,但这明显更慢。我还尝试将每个花色分成2-7,8-A,看看在小组卡片上执行插入排序是否更快,但这也明显更慢。所以我的结论是不要浪费时间过多地递归来做桶排。
将此方法推广到您的卡片,似乎最好的方法是将卡片分成易于一次性手动排序的大小的桶(例如10或20张牌,因为很容易确定它们属于哪个桶),然后对桶进行插入排序。据推测,您应该能够以这种方式在大约6-7分钟内将您的216张牌排序完成。

1

我认为计数排序与你的插入排序方法结合起来可能效果很好:先扫描一遍找到所有的1,然后放在最前面,接着是2,以此类推。

虽然你的卡片编号从1到200多,看起来工作量很大,但我认为在这种情况下,一切都会变得很繁琐。你可以通过同时处理多张卡片来加快速度,这应该不太难:同时扫描所有的1、2和3(如果你愿意还可以更多),并将它们放在相应的位置上(与“插入排序”相结合,这样你就不必在卡片之间留出空白的位置了)。


0

有一种专门用于整理纸牌的方法:它被称为耐心排序。

http://geeksforgeeks.org/patience-sorting/

更新的文本描述: 有两个阶段来对一副牌进行排序:

  1. 形成几堆
  2. 从堆中收集牌
  • 低价值的卡牌可以放在上面。
  • 如果没有可能的位置,那么可以创建一个新的堆。
  • 目标是尽可能形成尽可能少的堆。
  • 要收集卡牌非常容易,因为所有堆的顶部卡牌按从低到高的顺序变得可见。


您引用的链接很棒,但答案必须是自给自足的,以防链接失效。 - TUI lover

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接