【发布时间】:2013-05-04 06:32:47
【问题描述】:
目前我有一个整数列表。此列表包含指向另一个更大列表中的“活动”对象的索引值。如果较小的“活动”值列表变得太大,它会触发循环遍历小列表并删除已变为非活动的值。目前,它通过简单地忽略不活动的值并将它们添加到第二个列表来删除它们(当第二个列表再次变满时,重复相同的过程,将它们放回第一个列表等等)。
发生此触发器后,列表将使用快速排序实现进行排序。这一切都很好。
-------问题------
但是,我看到了速度的潜在提升。我正在想象在进行排序的同时删除非活动值。不幸的是,我找不到以这种方式实现快速排序的方法。仅仅因为快速排序与枢轴一起使用,这意味着如果从列表中删除值,枢轴最终将尝试访问列表中不存在的插槽等。(除非我只是想错了) .
那么,关于如何结合这两个操作的任何想法?我似乎找不到任何可以处理这个问题的快速排序算法,或者我只是没有看到如何将它实现到快速排序中......任何提示都表示赞赏!
用于更好地了解当前情况的代码: (当前条件:值的范围可以从 0 到 200 万,没有两个值是相同的,并且通常它们大多是排序的,因为它们经常被排序)
if (deactive > 50000)//if the number of inactive coordinates is greater than 50k
{
for (int i = 0; i < activeCoords1.Count; i++)
{
if (largeArray[activeCoords[i]].active == true)//if coordinate is active, readd to list
{
activeCoords2.Add(activeCoords1[i]);
}
}
//clears the old list for future use
activeCoords1.Clear();
deactive = 0;
//sorts the new list
Quicksort(activeCoords2, 0, activeCoords2.Count() - 1);
}
static void Quicksort(List<int> elements, int left, int right)
{
int i = left, j = right;
int pivot = elements[(left + right) / 2];
while (i <= j)
{
// p < pivot
while (elements[i].CompareTo(pivot) < 0)
{
i++;
}
while (elements[j].CompareTo(pivot) > 0)
{
j--;
}
if (i <= j)
{
// Swap
int tmp = elements[i];
elements[i] = elements[j];
elements[j] = tmp;
i++;
j--;
}
}
// Recursive calls
if (left < j)
{
Quicksort(elements, elements, left, j);
}
if (i < right)
{
Quicksort(elements, elements, i, right);
}
}
【问题讨论】:
-
如果列表大部分是排序的,使用快速排序不是一个好主意,因为在排序列表上快速排序变成 O(n^2)。
-
因为数字范围在0到2000000之间,所以可以使用计数排序,似乎不需要过多的合并操作。
-
不幸的是,我相信计数排序会撤消某些连接,因为值似乎是重新生成而不是移动。我需要保持每个值引用完好无损,因为对象还需要保持它们的指针指向正确的值......它有点晦涩,但它需要保持这种状态。 ://
-
我遗漏了一些东西 - 如果您要从中删除项目 (
activeCoords1) 的列表已经排序,那么您要复制项目的列表 (activeCoords2) 也将排序因为您以与activeCoords相同的顺序向其中添加项目。我错过了什么? -
另外:(1) 您的 Quicksort 示例无法编译(
oldList?是什么)和 (2) 它使用的是List<int>,因此要比较的元素是ints,但您有调用.CompareTo()来比较它们的巨大开销——为什么不直接比较呢?哦,(3)如果你真的,真的需要让它尽可能快,你将不得不使用普通数组而不是List<T>...