这里基本上是我的旧问题的后续问题:Choosing specific objects satisfying conditions
我有称为变量的对象,可以分配或取消分配。每个变量都有一个域,这意味着可以为变量赋值。例如,变量可能采用1到32之间的值。我可以使用非常高度优化的方法在恒定时间内查询变量的大小。
一个重要的操作是以某种方式找到具有最小域大小的未分配元素的范围。为此,我有一个指向所有变量对象的指针向量。记账完成是为了保持一个不变量,表示指向所有未分配变量的指针首先出现在所有已分配的变量之前。
随着时间的推移,变量会以动态方式发生变化,其域大小会发生变化,未分配的变量可能会被分配,反之亦然。当变量的状态发生变化时,它们会被交换,以便再次保持不变量。这意味着在整个程序执行过程中向量的大小保持不变。
然后我的问题是:有效地找到具有最小域大小的未分配变量的范围。我现在在做什么:用指针向量保持不变量。然后,当我需要找到元素范围时,我完全对包含指向未分配变量的指针的部分进行排序。
这非常慢。根据Visual Studio分析器,我使用大约50%的总时间排序。我正在排序的这些指针元素范围非常小,最多500-600个元素。这有可能的原因吗?
实际上在此方案之前,我使用的是一种不依赖于排序的方法。它感觉它应该更慢,甚至渐近它。我看到我的新方案对性能产生了很大的负面影响,排序是做最多工作的人。
有什么我可以尝试的吗?在现代硬件上排序500-600个元素应该是正确的(并且使用std :: sort)? std :: partial_sort也没有真正改变这种情况。
我有点不确定我是否能为您提供更多有用的信息,但如果有什么事情请告诉我。无论是什么导致它,我都对这种现象感到震惊。如果这很重要,我正在使用C ++,但我认为这可以被视为与语言无关的问题。
编辑:以下是一个简单示例:
此向量中的零表示已分配的变量,非零元素表示具有该域大小的未分配变量。让我们说我的矢量看起来像这样:
{1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 0, 0, 0, 0, 0}
然后我的算法采取一步并改变变量的状态。然后矢量看起来像
{2, 0, 3, 3, 3, 4, 4, 3, 3, 3, 4, 5, 0, 0, 1, 0, 0}
现在违反了不变量:前面有未分配的变量。我需要做点什么来纠正这个。然后我需要找到具有最小值的元素范围。例如,修复和排序会产生:
{1, 2, 3, 3, 3, 3, 3, 3, 4, 4, 4, 5, 0, 0, 0, 0, 0}
EDIT2:
有关此问题的其他详细信息。未分配变量的潜在不同值范围不多。我事先知道它,最大值总是最多32,其中1总是最低值。值的更改可能出现在元素集中的任何位置,但是当它发生时,在一个步骤中,每个更改的值最多改变1.然后,我需要找到具有最低值的所有元素。
是的,我相信在执行簿记时可以执行重新排序。我们可以假设我们从排序范围开始并且不变量成立。但接下来的问题是,人们如何实际进行重新排序?好吧,可能我应该检查哪些元素已经改变,并以某种方式让它们漂浮到正确的位置。任何想法如何做到这一点(在代码级别)?数据结构本身是一个好主意吗?
第一次编辑有点误导,现在已经纠正了。所以范围总是最多500-600个元素,许多连续值在很小的范围内(最多1到32个)。
EDIT3:
如果有人好奇,我会解释之前的方法要快得多并且不依赖于排序。我相信所有这些都可以更有效地完成,这就是为什么我想尝试改用另一种方案。
这个想法如下:在每一点上,我都会有一个指针向量,其中只包含 具有最小域值的元素。然后算法完成它的工作,并且变量发生了变化。首先,我对所有变量进行线性扫描,并检查最小域值是否已更改。如果有,我重建元素的向量。如果没有,我检查小范围的指针,并添加或删除元素以使再次保持不变(容器保存所有具有最小域的未分配变量)。
我有一种直觉,我的新方案可以更快,因为矢量的大小保持不变,元素只在其中交换或旋转。但我可能完全错了,很难说硬件真正有效。
答案 0 :(得分:0)
如果我明确指出它,你只需要对物体进行大约500-600个指针,但它对你来说太慢了。首先使用什么算法?某些算法在大多数排序数据中几乎具有线性复杂性如果你的数据只包含一些未排序的元素,你可能想尝试插入排序(在avarage上需要O(n ^ 2),它在大多数排序的数据上运行良好),或TimSort(它有点难以实现,但它真的快)。
我不知道1..32范围是否只是一个例子,但如果你真的使用这么小的一组值,最快的排序方式是你创建32个列表(例如链表) ,当你遇到值X时,你把它放在第X个列表中。完成后,选择第一个非空列表,然后就可以了。