我需要在一个小数组中“插入”给定索引处的元素.也就是说,将具有较大索引1的所有元素移动到右侧. .NET中最快的方法是什么? 注意:我添加了自己的答案,但我仍在寻找解释和更快的
注意:我添加了自己的答案,但我仍在寻找解释和更快的替代方案.
编辑:我确实需要一个数组,而不是List< T>而不是链表.
更新:由于我没有得到奇怪的性能结果的解释,我已经分别问了这个问题:Why is copying references to strings much slower than copying ints (but vice versa for Array.Copy())?
有两种明显的方法:逐个使用Array.Copy和复制元素:private static void ElementByElement<T>(T[] arg, int start) { for (int i = arg.Length - 1; i > start; i--) { arg[i] = arg[i - 1]; } } private static T BuiltInCopy<T>(T[] arg, int start) { Array.Copy(arg, start, arg, start + 1, arg.Length - start - 1); return arg[0]; }
一方面,List< T> insert使用Array.Copy.另一方面,Array.Copy是非泛型的,可以做很多额外的工作:http://msdn.microsoft.com/en-us/library/z50k9bft.aspx
我希望Array.Copy更快.然而,这次MiniBench测试的结果让我感到惊讶.
internal class Program { private static int smallArraySize = 32; public static void Main(string[] args) { BenchArrayCopy(); } private static void BenchArrayCopy() { var smallArrayInt = new int[smallArraySize]; for (int i = 0; i < smallArraySize; i++) smallArrayInt[i] = i; var smallArrayString = new string[smallArraySize]; for (int i = 0; i < smallArraySize; i++) smallArrayString[i] = i.ToString(); var smallArrayDateTime = new DateTime[smallArraySize]; for (int i = 0; i < smallArraySize; i++) smallArrayDateTime[i] = DateTime.Now; var moveInt = new TestSuite<int[], int>("Move part of array right by 1: int") .Plus(BuiltInCopy, "Array.Copy()") .Plus(ElementByElement, "Element by element in a for loop") .RunTests(smallArrayInt, 0); var moveString = new TestSuite<string[], string>("Move part of array right by 1: string") .Plus(BuiltInCopy, "Array.Copy()") .Plus(ElementByElement, "Element by element in a for loop") .RunTests(smallArrayString, "0"); var moveDT = new TestSuite<DateTime[], DateTime>("Move part of array right by 1: DateTime") .Plus(BuiltInCopy, "Array.Copy()") .Plus(ElementByElement, "Element by element in a for loop") .RunTests(smallArrayDateTime, smallArrayDateTime[0]); moveInt.Display(ResultColumns.All, moveInt.FindBest()); moveString.Display(ResultColumns.All, moveInt.FindBest()); moveDT.Display(ResultColumns.All, moveInt.FindBest()); } private static T ElementByElement<T>(T[] arg) { int start = 8; for (int i = smallArraySize - 1; i > start; i--) { arg[i] = arg[i - 1]; } return arg[0]; } private static T BuiltInCopy<T>(T[] arg) { int start = 8; int length = smallArraySize - start - 1; Array.Copy(arg, start, arg, start + 1, length); return arg[0]; } }
以下是两次运行的结果:
f:\MyProgramming\TimSort\Benchmarks\bin\Release>Benchmarks.exe ============ Move part of array right by 1: int ============ Array.Copy() 568475865 0:31.606 1,73 Element by element in a for loop 980013061 0:31.449 1,00 ============ Move part of array right by 1: string ============ Array.Copy() 478224336 0:31.618 2,06 Element by element in a for loop 220168237 0:30.926 4,38 ============ Move part of array right by 1: DateTime ============ Array.Copy() 382906030 0:27.870 2,27 Element by element in a for loop 458265102 0:29.239 1,99 f:\MyProgramming\TimSort\Benchmarks\bin\Release>Benchmarks.exe ============ Move part of array right by 1: int ============ Array.Copy() 500925013 0:28.514 1,76 Element by element in a for loop 988394220 0:31.967 1,00 ============ Move part of array right by 1: string ============ Array.Copy() 483178262 0:30.048 1,92 Element by element in a for loop 193092931 0:27.642 4,43 ============ Move part of array right by 1: DateTime ============ Array.Copy() 450569361 0:30.807 2,11 Element by element in a for loop 568054290 0:31.385 1,71
也就是说,对于int和DateTime,ElementByElement明显更快;而对于字符串,BuiltInCopy的速度是ElementByElement的两倍(并且是int的ElementByElement的两倍).我希望int和string的结果在32位机器上非常相似,因为堆栈上对字符串的引用与int的大小相同,除了读写堆栈内存之外不应该涉及任何操作.