当前位置 : 主页 > 手机开发 > 无线 >

.net – 将数组的一部分向右移动的最快方法

来源:互联网 收集:自由互联 发布时间:2021-06-10
我需要在一个小数组中“插入”给定索引处的元素.也就是说,将具有较大索引1的所有元素移动到右侧. .NET中最快的方法是什么? 注意:我添加了自己的答案,但我仍在寻找解释和更快的
我需要在一个小数组中“插入”给定索引处的元素.也就是说,将具有较大索引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的大小相同,除了读写堆栈内存之外不应该涉及任何操作.

网友评论