如何加快循环一百万个值数组的过程?

时间:2019-07-11 14:20:39

标签: c# arrays loops

因此,我正在进行在线测试,其中我必须实现一段代码来简单地检查该值是否在数组中。我写了以下代码:

    using System;
    using System.IO;
    using System.Linq;

    public class Check
    {
        public static bool ExistsInArray(int[] ints, int val)
        {
            if (ints.Contains(val)) return true;
            else return false;
        }
    }

现在我在这里没有看到任何问题,因为代码可以正常工作,但是由于数组包含百万个值,这样做“不够快”,所以我仍然无法通过测试。

我自己编写的唯一代码是:

    if (ints.Contains(val)) return true;
    else return false;

我可以使用的其他代码。

有没有办法加快这个过程?

谢谢。

编辑: 我碰到了一个页面,其中有人显然接受了与我相同的测试,这似乎可以节省CPU周期。

参考:How to save CPU cycles when searching for a value in a sorted list?

现在他在方法中的解决方案是:

    var lower = 0;
    var upper = ints.Length - 1;

    if ( k < ints[lower] || k > ints[upper] ) return false;
    if ( k == ints[lower] ) return true;
    if ( k == ints[upper] ) return true;

    do
    {
        var middle = lower + ( upper - lower ) / 2;

        if ( ints[middle] == k ) return true;
        if ( lower == upper ) return false;

        if ( k < ints[middle] )
            upper = Math.Max( lower, middle - 1 );
        else
            lower = Math.Min( upper, middle + 1 );
    } while ( true );

现在我明白了这段代码是如何工作的,但是我不清楚为什么这应该更快。如果有人可以详细说明会很好。

4 个答案:

答案 0 :(得分:8)

如果是已排序的数组,则可以使用 BinarySearch 来加快过程

public static bool ExistsInArray(int[] ints, int val)
{
    return Array.BinarySearch(ints, val) >= 0;
}

答案 1 :(得分:0)

如果输入数组已经排序,则最好使用BinarySearch。

.NET通过使用Array.BinarySearch方法内置了对BinarySearch的支持。

只需对包含和100万个整数值的排序数组进行包含和BinarySearch的快速实验即可。

public static void Main()
{
    var collection = Enumerable.Range(0, 1000000).ToArray();

    var st = new Stopwatch();

    var val = 999999;

    st.Start();

    var isExist = collection.Contains(val);

    st.Stop();

    Console.WriteLine("Time taken for Contains : {0}", st.Elapsed.TotalMilliseconds);

    t.Restart();

    var p = BinarySearchArray(collection, 0, collection.Length - 1, val);

    st.Stop();
    if(p == -1)
    {
        Console.WriteLine("Not Found");
    }
    else
    {
        Console.WriteLine("Item found at position : {0}", p);
    }

    Console.WriteLine("Time taken for binary search {0}", st.Elapsed.TotalMilliseconds);
}

private static int BinarySearchArray(int[] inputArray, int lower, int upper, int val)
{
    if(lower > upper)
        return -1;

    var midpoint = (upper + lower) / 2;

    if(inputArray[midpoint] == val)
    {
        return midpoint;
    }
    else if(inputArray[midpoint] > val)
    {
        upper  = midpoint - 1;              
    }
    else if(inputArray[midpoint] < val)
    {
        lower =  midpoint+1;    
    }

    return BinarySearchArray(inputArray, lower, upper, val);
}

以下是输出。

Time taken for Contains : 1.0518
Item found at position : 999999
Time taken for binary search 0.1522

很明显,BinarySearch在这里占了上风。

.NET的Contains方法在内部不使用BinarySearch。包含对于较小的集合很有用,但对于较大的数组,BinarySearch是更好的方法。

答案 2 :(得分:-1)

您可以使用Parallel,类似于以下代码:

namespace ParallelDemo
{
    class Program
    {
        static void Main()
        {
            var options = new ParallelOptions()
            {
                MaxDegreeOfParallelism = 2
            };
            List<int> integerList = Enumerable.Range(0,10).ToList();
            Parallel.ForEach(integerList, options, i =>
            {
                Console.WriteLine(@"value of i = {0}, thread = {1}",
                    i, Thread.CurrentThread.ManagedThreadId);
            });

            Console.WriteLine("Press any key to exist");
            Console.ReadLine();
        }
    }
}

注意:它将加快速度,但是您将使用更多的内存

答案 3 :(得分:-1)

正确的答案是:取决于。

  • 列表是否排序?
  • 列表多大?
  • 您可以抛出多少个内核?

最简单的答案是Linq,尽管它的全部奇迹实际上是相当缓慢的。它需要大量反射,并且通常会在幕后执行大量工作。当易读性是您的主要目标时,这很棒。但是为了表现?不。

在单线程,未排序的列表中,老式的for循环将为您带来最佳效果。如果已排序,则二进制搜索或快速搜索的某些版本将是最佳的选择。

对于并行,C#具有并行类。但是请注意,如果列表足够小,则创建线程的开销可以克服您的搜索时间。

简单的单线程未排序答案:

    public static bool ExistsInArray(int[] ints, int val)
    {
        for( int index = 0, count = ints.GetLowerBound(0); index < count; ++index)
        {
            if (ints[index] == val) return true;
        }
        return false;
    }

您正在寻找的网站很可能想要这个。但这仅在数组已排序的情况下有效。

    public static bool ExistsInArray(int[] ints, int val)
    {
        return Array.BinarySearch(ints, val) > 0;
    }

证明Linq不够快的辅助帖子。