我不明白:为什么我的插入排序实现每次都要超过合并排序,而不是任何大小的n
public List<Int32> InsertionSort(List<Int32> elements, Boolean ascending = true)
{
for (Int32 j = 1; j < elements.Count; j++)
{
Int32 key = elements[j];
Int32 i = j - 1;
while (i >= 0 && (elements[i].CompareTo(key) > 0) == ascending)
elements[i + 1] = elements[i--];
elements[i + 1] = key;
}
return elements;
}
public List<Int32> MergeSort(List<Int32> elements, Boolean ascending = true)
{
Sort(elements, 0, elements.Count - 1);
return elements;
}
private void MergeSort(List<Int32> elements, Int32 startIndex, Int32 count)
{
if(startIndex < count)
{
Int32 half = (startIndex + count).Divide(2, RoundMethod.Floor);
Sort(elements, startIndex, half);
Sort(elements, half + 1, count);
Merge(elements, startIndex, half, count);
}
}
public List<Int32> Merge(List<Int32> elements, Int32 lowerBound, Int32 half, Int32 upperBound)
{
Int32 i = 0;
Int32 j = 0;
Int32 lowerElementsCount = half - lowerBound + 1;
Int32 upperElementsCount = upperBound - half;
List<Int32> left = new List<Int32>();
while (i < lowerElementsCount)
left.Add(elements[lowerBound + i++]);
List<Int32> right = new List<Int32>();
while (j < upperElementsCount)
right.Add(elements[half + j++ + 1]);
left.Add(Int32.MaxValue);
right.Add(Int32.MaxValue);
i = 0;
j = 0;
for (int k = lowerBound; k <= upperBound; k++)
if (left[i] <= right[j])
{
elements[k] = left[i];
i++;
}
else
{
elements[k] = right[j];
j++;
}
return elements;
}
以下是我的研究结果:
SORTING 1 ELEMENTS
MERGE-SORT: TIME SPENT: 0ms (1513 ticks)
INSERTION-SORT: TIME SPENT: 0ms (1247 ticks)
SORTING 10 ELEMENTS
MERGE-SORT: TIME SPENT: 1ms (2710 ticks)
INSERTION-SORT: TIME SPENT: 0ms (3 ticks)
SORTING 100 ELEMENTS
MERGE-SORT: TIME SPENT: 0ms (273 ticks)
INSERTION-SORT: TIME SPENT: 0ms (11 ticks)
SORTING 1000 ELEMENTS
MERGE-SORT: TIME SPENT: 1ms (3142 ticks)
INSERTION-SORT: TIME SPENT: 0ms (72 ticks)
SORTING 10000 ELEMENTS
MERGE-SORT: TIME SPENT: 18ms (30491 ticks)
INSERTION-SORT: TIME SPENT: 0ms (882 ticks)
以及测试代码:
static void Main(string[] args)
{
for (int i = 1; i < 100000; i*=10)
{
List<Int32> elements = GetFilledList(i, 0, Int32.MaxValue, false);
Console.WriteLine("SORTING {0} ELEMENTS", elements.Count);
Stopwatch sw = new Stopwatch();
//MERGE SORT
sw.Start();
new MergeSort().Sort(elements);
sw.Stop();
Console.WriteLine("MERGE-SORT: TIME SPENT: {0}ms ({1} ticks)", sw.ElapsedMilliseconds, sw.ElapsedTicks);
//INSERTION SORT
sw.Restart();
new InsertionSort().Sort(elements);
sw.Stop();
Console.WriteLine("INSERTION-SORT: TIME SPENT: {0}ms ({1} ticks)", sw.ElapsedMilliseconds, sw.ElapsedTicks);
Console.WriteLine();
}
Console.ReadKey();
}
如果有人想知道我从算法导论,Thomas H. Cormen (作者),Charles E. Leiserson (作者),Ronald L. Ri背心(作者),Clifford Stein (作者)那里得到了这些算法
编辑:
static List<Int32> GetFilledList(Int32 quantity, Int32 lowerBound, Int32 upperBound, Boolean mayRepeat = true)
{
List<Int32> numbers = new List<Int32>();
Random r = new Random();
for (int i = 0; i < quantity; i++)
{
Int32 numero = r.Next(lowerBound, upperBound);
while(!mayRepeat && numbers.Contains(numero))
numero = r.Next(lowerBound, upperBound);
numbers.Add(numero);
}
return numbers;
}
发布于 2011-11-28 23:52:07
因为在合并排序之后,元素中的对象已经排序。再做一次
elements = GetFilledList(i, 0, Int32.MaxValue, false);
在
sw.Restart();
发布于 2011-11-28 23:51:36
对10000个元素进行排序远远不足以有效地评估一个算法。越大越好。
另外,输入是随机的吗?发布您的GetFilledList
实现
和您需要在执行插入排序之前取消对elements
的排序(或者重新初始化elements
__)。
如果你按顺序翻转排序,会发生什么?我猜您正在用mergesort完成所有的工作,然后插入排序只是对已经排序的列表进行排序,它实际上非常擅长(O(n),假设一个正常的实现)。
发布于 2011-11-28 23:57:24
对于小输入,插入排序应该比合并排序更快;O(N)就是这样工作的。
f(n) = O(g(n)) if for all n, greater than n0, f(n) < C * g(n)
具有良好复杂性的算法通常具有较高的C值,因此在获得大量输入之前,它们不会真正超越“较慢”的算法。
虽然esskar似乎已经发现了您面临的主要问题,但请记住,在将来,您可能需要用更大的输入来测试算法,才能真正看到更好的算法。
https://stackoverflow.com/questions/8304021
复制相似问题