对索引值数组进行排序,打包和重新映射,以最大限度地减少重叠

时间:2010-07-02 07:48:24

标签: c++ algorithm sorting

Sitation:

概述

我有这样的事情:

std::vector<SomeType> values;
std::vector<int> indexes;

struct Range{
    int firstElement;//first element to be used in indexes array
    int numElements;//number of element to be used from indexed array
    int minIndex;/*minimum index encountered between firstElement 
        and firstElements+numElements*/
    int maxIndex;/*maximum index encountered between firstElement 
        and firstElements+numElements*/
    Range()
        :firstElement(0), numElements(0), minIndex(0), maxIndex(0){
    }
}

std::vector<Range> ranges;

我需要对值进行排序,重新映射索引并重新计算范围,以最大限度地减少每个范围的maxValueIndex-minValueIndex。

细节:

values 是某种类型的数组(好的,“向量”)(与哪一种无关)。 中的元素可能是唯一的,但这不能保证。

索引是一个int的向量。 “indices”中的每个元素都是与 values 中的某个元素对应的索引。索引中的元素不是唯一的,一个值可能会重复多种类型。而index.size()&gt; = values.size()。

现在,范围对应于来自索引的数据“块”。 firstElement是要从索引使用的元素的索引(即使用如下:indices [range.firstElement]),numElements是(显然)要使用的元素数,minIndex是mininum in(索引) [firstElement] ...索引[firstElement + numElements-1])a,d maxIndex在(indices [firstElement] ...索引[firstElement + numElements-1])中最大。范围从不重叠。 即对于每两个范围a,b

((a.firstElement >= b.firstElement) && (a.firstElement < (b.firstElement+b.numElements)) == false

显然,当我对(交换到元素等)进行任何操作时,我需要更新索引(因此它们一直指向相同的值),并重新计算相应的范围,因此范围是minIndex和maxIndex都是正确的。

现在,我需要以最小化Range.maxIndex - Range.minIndex的方式重新排列。包装后我不需要“最好”的结果,“可能是最好的”或“好”的包装就足够了。

问题:
重新映射索引和重新计算范围很容易。问题是我不确定如何对中的元素进行排序,因为在多个范围内可能会遇到相同的索引。

关于如何进行的任何想法?

限制:

不允许更改容器类型。容器应该是类似阵列的。没有地图,没有列表。 但是你可以在排序过程中随意使用你想要的任何容器。 此外,没有增强或外部库 - 纯C ++ / STL,我真的只需要一个算法。

其他信息:

没有为SomeType定义更多/更少的比较 - 只有相等/不相等。 但是没有必要比较两个值,只有索引。

算法的目标是确保输出

for (int i = 0; i < indexes.size; i++){ 
    print(values[indexes[i]]); //hypothetical print function
}

排序前后相同,同时确保每个范围 Range.maxIndex-Range.minIndex(排序后)尽可能小,以合理的努力。 我不是在寻找一个“完美”或“最优”的解决方案,拥有“可能完美”或“可能是最优”的解决方案就足够了。

P.S。这是 NOT 作业。

2 个答案:

答案 0 :(得分:1)

这不是算法,只是一些人大声思考。如果副本太多,它可能会破坏。

如果没有重复项,您只需重新排列值,使索引为0,1,2,依此类推。因此,对于起点,让我们排除双引用的值并安排其余的

由于存在重复,因此您需要确定将它们粘贴在哪里。假设副本由范围r1,r2,r3引用。现在,只要在min([r1,r2,r3] .minIndex)-1和max([r1,r2,r3] .maxIndex)+1之间插入副本,maxIndex-minIndex的总和将是相同的无论你在哪里插入它。将插入点向左移动将减少左侧所有范围的max-min,但是将其增加到右侧的所有范围。因此,我认为明智的做法是在r1,r2,r3的最右边范围(最大minIndex之一)的左边(minindex)插入副本。重复所有重复项。

答案 1 :(得分:0)

好的,看起来只有一种方法可以可靠地解决这个问题:

确保通过复制值一次两个范围都没有使用索引。 即扫描整个索引数组,当您找到在多个范围内使用的索引(值)时,为每个范围添加该值的副本 - 每个范围都有唯一索引。之后这个问题就变得简单 - 您只需在排序将确保的值的方式值的阵列的第一只包含由第一范围内使用值,那么对于第二个范围值,等等。即这将获得最大的包装。

由于我的应用中更重要的是尽量减少之和(范围[I] .maxIndex范围,[I] .minIndex)值的该最小化数,此方法适用于我

我不认为有解决问题的其他可靠的方式 - 这是很容易得到的情况时有每隔范围内使用指标,在这种情况下,将不可能“包”的数据,无论你做什么。即使允许索引同时被两个范围使用也会导致问题 - 您可以获得范围a,b和c,其中a和b,b和c,a和c将具有公共索引。在这种情况下,也无法打包数据。