在排序后记住元素的“原始”索引

时间:2009-09-03 17:06:59

标签: sorting

说,我使用合并排序来对整数数组进行排序。现在我还需要记住元素在未排序数组中的位置。最好的方法是什么?

一种非常天真且占用空间的方法是(在C中)将每个数字维持为“结构”,而另一个数字存储其索引:

struct integer {
int value;
int orig_pos;
};

但是,显然还有更好的方法。如果您已经解决了这些问题,请分享您的想法和解决方案。如果您需要更多背景信息,请与我们联系。谢谢。

5 个答案:

答案 0 :(得分:2)

显然,对于N长数组,您需要存储SOME其中的N个整数 - 例如,每个项目的原始位置;编码“1中的N!”的任何其他方式可能性(即,实际上发生了什么排列)也将至少占用O(N)空间(因为,通过斯特林的近似,log(N!)约为N log(N)......)。

所以,我不明白为什么你认为“空间消耗”最简单直接地存储这些指数。当然还有其他可能性(占用相似的空间):例如,您可以创建N个索引的单独辅助数组,并对辅助数组进行排序(基于该索引处的值),仅保留原始索引。这意味着以排序顺序访问数据的额外级别的间接性,但是如果您对大型结构的数组进行排序,则可以节省大量数据移动,因此存在性能折衷......但空间消耗基本上是相同! - )

答案 1 :(得分:1)

struct这么糟糕吗?对我来说,替代方案是一系列指针。

答案 2 :(得分:1)

我觉得在这个问题中你必须考虑一个古老的问题:速度与大小。在任何一种情况下,您都保留了数据的新表示形式(排序数组)和数据的旧表示形式(数组用于查看的方式),因此您的解决方案本身就会有一些数据复制。如果你正在对n个数字进行排序,并且你需要记住它们在这些n个数字被分类之后需要记住,你将不得不在某个地方存储n个信息,没有解决这个问题。

只要您接受将剩余的空间量增加一倍,就可以保留这些旧数据,那么您应该考虑具体的应用程序并决定哪些更快。一种选择是在对数组进行排序之前制作数组的副本,但是解决后来可能会变成O(N)问题的地方。从这个角度来看,如果它符合您稍后使用数据的方式,那么建议在结构中添加另一个int似乎不是一个坏主意。

答案 3 :(得分:1)

这看起来像我使用索引排序的情况。以下C#示例演示了如何使用lambda表达式执行此操作。我是使用lambdas的新手,但他们可以很容易地完成一些复杂的任务。

// first, some data to work with
List<double> anylist = new List<double>;
anylist.Add(2.18);  // add a value
...                 // add many more values
// index sort
IEnumerable<int> serial = Enumerable.Range(0, anylist.Count);
int[] index = serial.OrderBy(item => (anylist[item])).ToArray();
// how to use
double FirstValue = anylist[index[0]];
double SecondValue = anylist[index[1]];

当然,任何列表仍然是原始顺序。

答案 4 :(得分:0)

  • 您可以按照提议的方式进行

  • 您也可以保留原始未排序数组的副本(意味着您可以使用非就地排序算法)

  • 您可以创建仅包含原始索引的附加数组

这三种方式同样占用空间,没有“更好”的方式。你可以使用short而不是int来安全空间,如果你的数组不会得到> 65k元素(但要注意你的建议结构填充)。