简体   繁体   English

C++:检查所有数组元素是否相等的最快方法

[英]C++: Fastest method to check if all array elements are equal

What is the fastest method to check if all elements of an array(preferable integer array) are equal.检查数组(最好是整数数组)的所有元素是否相等的最快方法是什么。 Till now I have been using the following code:到目前为止,我一直在使用以下代码:

bool check(int array[], int n)
{   
    bool flag = 0;

    for(int i = 0; i < n - 1; i++)      
    {         
        if(array[i] != array[i + 1])
            flag = 1;
    }

    return flag;
}
int check(const int a[], int n)
{   
    while(--n>0 && a[n]==a[0]);
    return n!=0;
}

Here is a solid solution which is valid C++11.这是一个有效的 C++11 的可靠解决方案。 The advantages is that you do not need to manually play with the indexes or iterators.优点是您不需要手动使用索引或迭代器。 It is a best practice to最好的做法是

prefer algorithm calls to handwritten loops [Herb Sutter - C++ Coding Standards]更喜欢算法调用而不是手写循环 [Herb Sutter - C++ 编码标准]

I think this will equally efficient as Paul R's solution.我认为这与 Paul R 的解决方案同样有效。

bool check(const int a[], int n)
{
      return !std::all_of(a, a+n, [a](int x){ return x==a[0]; });
}

Once you have found a mismatching element you can break out of the loop:一旦找到不匹配的元素,就可以跳出循环:

bool check(const int array[], int n)
{   
    for (int i = 0; i < n - 1; i++)      
    {         
        if (array[i] != array[i + 1])
            return true;
    }
    return false;
}

If this is performance-critical then it can be further optimised slightly as:如果这对性能至关重要,那么它可以进一步优化为:

bool check(const int array[], int n)
{   
    const int a0 = array[0];

    for (int i = 1; i < n; i++)      
    {         
        if (array[i] != a0)
            return true;
    }
    return false;
}

Recast the array to a larger data type.将数组重新转换为更大的数据类型。 Eg, operate on 64bit ints, or use SSE or AVX intrinsics for 128 or 256 bit operation.例如,操作 64 位整数,或使用 SSE 或 AVX 内部函数进行 128 或 256 位操作。 For example, the SSE2 intrinsic is _mm_cmpeq_epi32, whose result you'll use with _mm_or_si128.例如,SSE2 内在函数是 _mm_cmpeq_epi32,其结果将与 _mm_or_si128 一起使用。 Check the result with repeated application of _mm_srli_si128 and _mm_cvtsi128_si32.用_mm_srli_si128 和_mm_cvtsi128_si32 的重复应用检查结果。 Check the result every few hundred iterations for early exit.每隔几百次迭代检查一次结果,以便提前退出​​。

Make sure to operate on aligned memory, check the unaligned start and end as ints, and check the first packed element with itself.确保在对齐的内存上操作,检查未对齐的开始和结束为整数,并检查第一个打包元素本身。

We'll it's basically an O(n) operation so you can't do much better than what you have, other than dispensing with the flag and just return false;我们将它基本上是一个 O(n) 操作,所以你不能做得比你现有的好多少,除了取消标志并return false; on the first failure and return true;第一次失败并return true; after the iteration.迭代之后。

bool check(int array[],int n)
{       
  // here 1st element is checked with others. This decreases the number of iteration by 1.
  // also it returns immediately. 
  // The requirement is to check if all the elements are equal. 
  // So if 1st element is equal to others then all elements are equal. 
  // Otherwise the  elements are not equal.
  for(int i=1;i<n;i++)      
  {         
    if(array[0]!=array[i])
      return false;
  }        
  return true;
}

Find a library that's available on your platform that supports threading or parallel-for loops, and split the computation out such that different cores test different ranges of the array.找到在您的平台上可用的支持线程或并行 for 循环的库,并将计算拆分出来,以便不同的内核测试不同的数组范围。

Some available libraries are listed here:这里列出了一些可用的库:

http://parallel-for.sourceforge.net/parallelfor.html http://parallel-for.sourceforge.net/parallelfor.html

Or possibly, you can make use of the parallism that many GPU's offer.或者,您可以利用许多 GPU 提供的并行性。

In theory, I would propose this:从理论上讲,我会提出以下建议:

bool check_single(const int a[], int n)
{
    for (int i = 1; i < n; ++i) {
        if (a[0] != a[n]) { return false; }
    }
    return true;
}

Compared to other (already proposed) versions:与其他(已经提出的)版本相比:

  • a[0] will be hoisted outside the loop by the compiler, meaning a single array access within the loop a[0]将被编译器提升到循环外,这意味着循环内的单个数组访问
  • we loop from 0 to n, which is better (access-wise) than loading a[0] and then looping from a[n]我们从 0 到 n 循环,这比加载a[0]然后从a[n]循环更好(访问方式)

Obviously, it still checks N elements and thus is O(N).显然,它仍然检查 N 个元素,因此是 O(N)。

For programmer efficiency you may try the following all in one line.为了提高程序员的效率,您可以在一行中尝试以下所有内容。

vector<int> v{1, 1, 1, 1};
all_of(v.cbegin(), v.cend(), [&r=v[0]](int value){ return value == r; }->bool);

I did not test run this code, let me know if there is syntax error.我没有试运行这段代码,如果有语法错误,请告诉我。

fast hash mapping technique:快速哈希映射技术:

bool areSame(int a[],int n)
{
    unordered_map<int,int> m; //hash map to store the frequency od every

    for(int i=0;i<n;i++)
       m[a[i]]++;
      
    if(m.size()==1)
       return true;
    else
       return false;
}

I think the following is more readable than the highest rated answer and I would wager more efficient too (but havent benchmarked)我认为以下内容比评分最高的答案更具可读性,我也打赌效率更高(但尚未进行基准测试)

bool check(int a[], int n)
{   
    if (n)
    {
        auto first = a[0];
        
        for(int i = 1; i < n; i++)      
        {         
            if(array[i] != first) return false;
        }
        
        return true;
    }

    return true;    //change to false for the OPs logic.  I prefer logical true here
}
bool check_identity (int a[], int b[], const int size)
{
    int i;
    i = 0;
    while ((i < size-1) && (a[i] == b[i]))   i++;

    return (a[i] == b[i]);

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM