我想将带有排序值的两个数组合并为一个。由于两个源数组都存储为大型数组的后续部分,我想知道,如果您知道将它们合并到大型存储中的方法。意思是inplace合并。
我找到的所有方法都需要一些外部存储空间。它们通常需要sqrt(n)临时数组。没有它,有没有一种有效的方法?
我正在使用C#。其他语言也欢迎。提前谢谢!
答案 0 :(得分:4)
AFAIK,合并两个(甚至是已排序的)数组在没有显着增加必要的比较和元素移动数量的情况下无法正常工作。见:merge sort。但是,存在阻塞的变体,它们能够通过利用一个长度为sqrt(n)的临时数组来排序长度为n的列表 - 正如你所写的那样 - 仍然保持操作数量相当低。它还不错 - 但它也是不是“没有”,显然是你能得到的最好的。
对于实际情况,如果您负担得起,最好使用临时数组来合并列表。
答案 1 :(得分:2)
如果值存储为较大数组的后续部分,则只需要对数组进行排序,然后删除相等的连续值。
void SortAndDedupe(Array<T> a)
{
// Do an efficient in-place sort
a.Sort();
// Now deduplicate
int lwm = 0; // low water mark
int hwm = 1; // High water mark
while(hwm < a.length)
{
// If the lwm and hwm elements are the same, it is a duplicate entry.
if(a[lwm] == a[hwm])
{
hwm++;
}else{
// Not a duplicate entry - move the lwm up
// and copy down the hwm element over the gap.
lwm++;
if(lwm < hwm){
a[lwm] = a[hwm];
}
hwm++;
}
}
// New length is lwm
// number of elements removed is (hwm-lwm-1)
}
在您断定这将太慢之前,请实施它并对其进行分析。这应该需要大约十分钟。
编辑:这当然可以通过使用不同的排序而不是内置排序来改进,例如: Quicksort,Heapsort或Smoothsort,取决于它在实践中提供更好的性能。请注意,硬件架构问题意味着实际性能比较可能与大O分析的结果非常不同。
您真的需要在实际的硬件/操作系统平台上使用不同的排序算法对其进行分析。
注意:我没有尝试在这个答案中给出一个学术答案,我试图给出一个实际的答案,假设你正试图解决一个真正的问题。
答案 2 :(得分:2)
不关心外部存储。 sqrt(n)甚至更大不应该损害你的表现。您只需要确保存储已合并。特别是对于大数据。特别是将它们合并在循环中。否则,GC将会受到压力并占用相当一部分CPU时间/内存带宽。