我希望对大量数组进行排序,大小大致相同,可以说30个元素,大多数顺序相同。 鉴于我知道一个数组的排序顺序,称之为模板并假设它与其他数组非常相似,我如何使用这些知识快速对其余数组进行排序?
与我们选择的模板相比,大多数数组只会丢失或有额外的一两个(很少更多)值。
我想避免使用已知顺序填充临时数组并对其应用常规排序算法的方法。事实上,我希望能够简单地按排序顺序读取数组并调整少数无序元素(并且我很乐意解释为什么这不可能或不可能)。
这似乎是一个已知的问题,是否已经有通用算法来实现这一目标?
这是基本的想法(编辑:但在此示例中,第二个数组的排序顺序完全相同且大小相同。在实际情况下,其他数组不是相同且大小和顺序略有不同):
#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
答案 0 :(得分:1)
是的,虽然在最坏的情况下(事实上数据没有类似的排序),但这会导致排序速度变慢。
从0
到n-1
的有序列表开始,其中n
是原始列表的长度。在排序第一个列表时,每次移动或交换原始列表中的元素时,也要移动此列表中的相应元素,我将其称为索引列表。
对第一个列表进行排序后,索引列表实际上是一个指向原始未排序列表的指针。因此,如果我们有firstunsorted
,firstsorted
和indexes
,那么对于i
到0
的任何n-1
,firstsorted[i] == firstunsorted[indexes[i]]
然后,您可以使用这些索引以相同的方式“预先”每个其他列表 - otherlist[i] = otherlistunsorted[indexes[i]]
为每个i
。
最后,选择具有良好最佳性能的第二种排序算法。例如,关于排序算法的维基百科页面建议插入排序或者弹出(或者如果你讨厌你的CS教授那么冒泡排序!)。您的第二个排序过程将使用它来完成每个列表的排序。
我们不会通过进行此更改来添加任何比较 - 在初始排序的平均情况下,它仍然是O(n log n)
,您只需要进行两倍的分配(构建indexes
)。在其他列表中,这在技术上并不比仅仅制作每个列表的副本更糟糕,因此每个列表的额外n
分配和第一个列表的n log n
分配。另一方面,如果你是对的并且列表的排序完全相同,那么第一个列表之后的所有列表都需要O(n log n)
到O(n)
的比较,这是你能得到的最好的