【问题标题】:Reusing a known sort operation to sort similarly unsorted data重用已知的排序操作对类似的未排序数据进行排序
【发布时间】:2013-09-18 16:14:32
【问题描述】:

我想对很多数组进行排序,它们的大小都大致相同,比如说 30 个元素,并且大部分都以相同的顺序排列。 鉴于我知道一个数组的排序顺序,将其称为模板并假设它与所有其他数组非常相似,我如何使用这些知识快速对其余数组进行排序?

与我们选择的模板相比,大多数数组只会丢失或具有额外的一两个(很少更多)值。

我想避免使用已知顺序填充临时数组并对其应用通用排序算法的方法。事实上,我希望能够简单地按排序顺序读取数组并针对少数无序元素进行调整(并且非常愿意解释为什么这不可能或可能不可能)。

这似乎是一个已知问题,是否已经有通用算法来实现这一点?

这是基本思想(edit:但在此示例中,第二个数组的排序顺序和大小完全相同。在实际情况下,其他数组不是 相同,但大小和顺序略有不同):

#begin with some random values
data = [13, 23, 41, 69, 12, 53, 63, 23, 25, 14, 37, 2, 39, 42, 99, 71, 91]
data_id = [(y, x) for x, y in enumerate(data)] #create pairs: (value, index)
s_data_id = sorted(data_id) #sort by value
s_data, s_order = zip(*s_data_id) #extract the sorted value and the index each came from

print "Sorted:", s_data
print "Order:", s_order

#other random values in the same order as the first (just for example they are exactly the same)
otherdata = [13, 23, 41, 69, 12, 53, 63, 23, 25, 14, 37, 2, 39, 42, 99, 71, 91]

#sort these values using the same order from the initial sort
s_ortherdata = [otherdata[s_order[i]] for i in range(len(s_order))]

print "Resorted:", s_ortherdata

http://codepad.org/60sdEqUu

【问题讨论】:

  • “相似”不相同。它们的顺序是否相同(不是值;order)?您最后的非代码注释似乎表明它们是,但这有助于澄清。有没有理由将其标记为 Python C?
  • “我想避免使用已知顺序填充临时数组并对其应用通用排序算法的方法。”为什么?似乎填充临时数组然后应用冒泡排序(从两端?)将是要走的路。

标签: python c arrays algorithm sorting


【解决方案1】:

是的,尽管在最坏的情况下(实际上数据没有类似排序)这会导致排序变慢。

0n-1 的有序列表开始,其中n 是原始列表的长度。在对第一个列表进行排序时,每次移动或交换原始列表中的元素时,也会移动此列表中的相应元素,我将其称为索引列表。

一旦你的第一个列表被排序,索引列表实际上是一个指向原始未排序列表的指针。所以,如果我们有firstunsortedfirstsortedindexes,那么对于从0n-1firstsorted[i] == firstunsorted[indexes[i]] 的任何i

然后,您可以使用这些索引以相同的方式“预排序”每个其他列表 - otherlist[i] = otherlistunsorted[indexes[i]] 对应每个 i

最后,选择具有良好最佳情况性能的第二种排序算法。例如,关于排序算法的 Wikipedia 页面推荐插入排序或 shellsort(如果你讨厌你的 CS 教授,也可以选择冒泡排序!)。您的第二次排序将使用它来最终确定每个列表的排序。

我们不会通过进行此更改来添加任何比较 - 在​​您初始排序的平均情况下,它仍然是 O(n log n),您只需进行两倍的分配(构建 indexes)。在其他列表中,从技术上讲,这并不比复制每个列表更糟糕,因此再次为每个列表添加一组n 分配,为第一个列表分配n log n。另一方面,如果你是对的并且列表的排序完全相同,那么第一个列表之后的所有列表都从需要 O(n log n)O(n) 比较,这是你能得到的最好的。

【讨论】:

  • 这不提供请求的行为,因为将第二次排序引起的排列应用于新数组可能会产生“非常未排序”的结果,因为在新数组中插入或删除元素相对于第一个可能会产生非常破坏性的影响。
  • 非常接近我所追求的,但如果可能的话,我不想复制数组。相反,只需按排序顺序阅读它们(我猜我会假设这需要一个缓冲区来存储和修复乱序元素。是的,在最坏的情况下,这将等于原始大小,但这将不常见并且可以是具体处理)。此外,如果indexes 的大小更大,我最终会出现间隙,并非所有值都从otherlistunsorted 复制,并且不能简单地用剩余部分填充尾部。
  • 要详细说明 EricPostpischil 的评论,假设新数组只是在列表的前面包含一个新值。 indexes 中的所有索引现在都无效,偏移 1 并且从我所看到的结果来看,最终只是对数据进行了洗牌。
猜你喜欢
  • 2017-07-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-09
  • 1970-01-01
  • 1970-01-01
  • 2017-07-16
相关资源
最近更新 更多