伪码:
S = {};
Loop 10000 times:
u = unsorted_fixed_size_array_producer();
S = sort(S + u);
我需要一个有效的sort实现,它接受一个排序数组和一个未排序数组,然后对它们进行排序。但是我们知道经过几次迭代后, size(S)将比 size(u)大得多,这是先验的。
更新:还有另一个先验: u 的大小已知,例如10或20,循环时间也是已知的。
更新:我实施了@Dukelnig在C https://gist.github.com/blackball/bd7e5619a1e83bd985a3中建议的算法,该算法符合我的需要。谢谢!
答案 0 :(得分:3)
排序u
,然后合并S
和u
。
合并只需要同时迭代两个已排序的数组,并选择较小的元素并在每一步递增该迭代器。
运行时间为O(|u| log |u| + |S|)
。
这与merge sort非常相似,因此可以从那里得到排序数组。
一些用于合并的Java代码,派生自Wikipedia :( C代码看起来不会那么不同)
static void merge(int S[], int u[], int newS[])
{
int iS = 0, iu = 0;
for (int j = 0; j < S.length + u.length; j++)
if (iS < S.length && (iu >= u.length || S[iS] <= u[iu]))
newS[j] = S[iS++]; // Increment iS after using it as an index
else
newS[j] = u[iu++]; // Increment iu after using it as an index
}
这也可以通过从后面进行就地(在S中,假设它有足够的额外空间) 这是一些有效的Java代码:
static void mergeInPlace(int S[], int SLength, int u[])
{
int iS = SLength-1, iu = u.length-1;
for (int j = SLength + u.length - 1; j >= 0; j--)
if (iS >= 0 && (iu < 0 || S[iS] >= u[iu]))
S[j] = S[iS--];
else
S[j] = u[iu--];
}
public static void main(String[] args)
{
int[] S = {1,5,9,13,22, 0,0,0,0}; // 4 additional spots reserved here
int[] u = {0,10,11,15};
mergeInPlace(S, 5, u);
// prints [0, 1, 5, 9, 10, 11, 13, 15, 22]
System.out.println(Arrays.toString(S));
}
为了减少比较次数,我们也可以使用二进制搜索(尽管时间复杂度保持不变 - 这在比较昂贵时非常有用)。
// returns the first element in S before SLength greater than value,
// or returns SLength if no such element exists
static int binarySearch(int S[], int SLength, int value) { ... }
static void mergeInPlaceBinarySearch(int S[], int SLength, int u[])
{
int iS = SLength-1;
int iNew = SLength + u.length - 1;
for (int iu = u.length-1; iu >= 0; iu--)
{
if (iS >= 0)
{
int index = binarySearch(S, iS+1, u[iu]);
for ( ; iS >= index; iS--)
S[iNew--] = S[iS];
}
S[iNew--] = u[iu];
}
// assert (iS != iNew)
for ( ; iS >= 0; iS--)
S[iNew--] = S[iS];
}
如果S
不必是数组
以上假设S
必须是一个数组。如果不是,binary search tree之类的内容可能会更好,具体取决于u
和S
的大小。
运行时间为O(|u| log |S|)
- 只需替换一些值即可查看哪个更好。
答案 1 :(得分:0)
如果您确实必须始终为S
使用文字数组,那么最好的方法是将新元素单独插入已经排序的{{1} }。即基本上对每个新批次中的每个元素使用经典插入排序技术。从某种意义上说,插入阵列是昂贵的(你必须移动元素),这将是昂贵的,但这是必须使用S
数组的代价。
答案 2 :(得分:0)
因此,如果S的大小远远大于u的大小,那么对于大多数排序的数组而言,这不是您想要的有效排序吗?传统上这将是插入排序。但是你只会通过实验和测量来了解真正的答案 - 尝试不同的算法并选择最好的算法。如果没有实际运行代码(也许更重要的是,使用您的数据),您就无法可靠地预测性能,即使使用与排序算法一样好的东西也是如此。
答案 3 :(得分:0)
假设我们有一个大型n
的大型排序列表和一个大小为k
的小型排序列表。
二进制搜索,从结尾开始(位置n-1
,n-2
,n-4
和&amp; c),作为较小列表中最大元素的插入点。将较大列表k
元素的尾端向右移动,插入较小列表的最大元素,然后重复。
因此,如果我们有列表[1,2,4,5,6,8,9]
和[3,7]
,我们会这样做:
[1,2,4,5,6, , ,8,9]
[1,2,4,5,6, ,7,8,9]
[1,2, ,4,5,6,7,8,9]
[1,2,3,4,5,6,7,8,9]
但我会建议你在使用有趣的合并程序之前,先对列表进行连接并对整个事情进行排序。