【问题标题】:Compare element in a vector with elements in an array比较向量中的元素与数组中的元素
【发布时间】:2014-07-30 19:35:35
【问题描述】:

我有两个数据结构,其中包含数据。

  • 一个是向量std::vector<int> presentStudents另一个是一个
  • char 数组 char cAllowedStudents[256];

现在我必须比较这两个,以便检查 vector 中的每个元素与 array 以便向量中的所有元素都应该存在于数组中,否则我将返回 false 如果有一个元素在不属于数组的向量中。

我想知道最有效和最简单的解决方案。我可以将我的int vector 转换为char array,然后一一比较,但这将是一个冗长的操作。有没有更好的方法来实现这一点?

【问题讨论】:

  • 集合是否已排序? char数组的长度是多少,我们知道256的大小。
  • 虽然我提供了我个人认为对您的情况最有效的答案,但我想提一件事:虽然免费提供的效率总是很好,但应该是如果这实际上只有大约 256 名学生,请在您的优先级列表的最底部。只要这个函数不在一个巨大的循环中被调用,我相信在这种情况下代码的清晰性和可维护性应该更重要。

标签: c++ arrays visual-c++ vector


【解决方案1】:

我建议您使用哈希映射 (std::unordered_map)。将 char 数组的所有元素存储在 hash map 中。

然后简单地依次检查向量中的每个元素,无论它是否存在于地图中,时间复杂度为 O(1)。

Total time complexity O(N), extra space complexity O(N).

请注意,您必须在编译器中启用 C++11。

【讨论】:

    【解决方案2】:

    请参考c++算法头文件中的set_difference()函数。您可以直接使用此功能,并检查结果差异集是否为空。如果不为空,则返回 false。

    更好的解决方案是调整 set_difference() 的实现,例如这里:http://en.cppreference.com/w/cpp/algorithm/set_difference,在您获得第一个不同元素后立即返回 false。

    示例改编:

    while (first1 != last1)
    {
        if (first2 == last2) 
            return false;
    
        if (*first1 < *first2)
        {
            return false;
        }
        else
        {
            if (*first2 == *first1)
            {
                ++first1;
            }
            ++first2;
        }
    }
    return true;
    

    【讨论】:

      【解决方案3】:
      1. 使用std::sortcAllowedstudents进行排序。
      2. 遍历presentStudents 并使用std::binary_search 在排序后的cAllowedStudents 中查找每个学生。
      3. 如果没有找到向量的项,则返回 false。
      4. 如果找到向量的所有元素,则返回true。

      这是一个函数:

      bool check()
      {
         // Assuming hou have access to cAllowedStudents
         // and presentStudents from the function.
      
         char* cend = cAllowedStudents+256;
         std::sort(cAllowedStudents, cend);
      
         std::vector<int>::iterator iter = presentStudents.begin();
         std::vector<int>::iterator end = presentStudents.end();
         for ( ; iter != end; ++iter )
         {
            if ( !(std::binary_search(cAllowedStudents, cend, *iter)) )
            {
               return false;
            }
         }
         return true;
      }
      

      另一种方式,使用std::difference

      bool check()
      {
         // Assuming hou have access to cAllowedStudents
         // and presentStudents from the function.
      
         char* cend = cAllowedStudents+256;
         std::sort(cAllowedStudents, cend);
      
         std::vector<int> diff;
         std::set_difference(presentStudents.begin(), presentStudents.end(),
                             cAllowedStudents, cend,
                             std::back_inserter(diff));
         return (diff.size() == 0);
      }
      

      【讨论】:

      • 为什么不使用std::set_difference之类的东西?
      • @billz std::set_difference 也可以。它会做同样的计算,但也会创建另一个容器。
      • @R Sahu:如果我错了,请纠正我,但binary_serach 不返回迭代器,而是返回布尔值。所以与 cend 的比较应该是没有必要的。
      • @billz:我喜欢set::difference 版本,因为它非常紧凑。但是,我不喜欢set_difference 的一点是(就标准而言)它不使用(不)相等运算符,而是两次使用 less 运算符。你知道这是否在实际实现中被优化了吗?
      • @maven 我的意思是,如果 yoz 复制了解决方案,您必须使数组在函数 check() 中可用。您是通过将 aray 设为全局变量还是将其作为参数传递给 check 来做到这一点的?
      【解决方案4】:

      使用 std::sort 对两个列表进行排序,并在数组上迭代地使用 std::find。

      编辑:诀窍是使用先前找到的位置作为下一次搜索的起点。

      std::sort(begin(pS),end(pS))
      std::sort(begin(aS),end(aS))
      
      auto its=begin(aS);
      auto ite=end(aS);
      
      for (auto s:pS) {
          its=std::find(its,ite,s);
          if (its == ite) {
              std::cout << "Student not allowed" << std::cout;
              break;
          }
      }
      

      编辑:正如传说中提到的,使用二分搜索通常可能更有效(如 R Sahu 的回答)。但是,对于小型数组,并且如果向量包含数组中很大一部分学生(我会说至少十分之一),二进制搜索的额外开销可能(或可能不会)超过其渐近复杂性的好处。

      【讨论】:

      • 那效率很低,不是吗?为什么在排序时使用std::find
      • 数组可能是向量中数字的超集。您也可以从最后找到的元素的位置开始搜索。这样,您可以在列表排序后实现线性复杂性。
      • @legends2k 但我承认,对于这么短的列表,对所有元素进行简单的暴力搜索可能会更有效
      【解决方案5】:

      使用 C++11。在您的情况下,size 是 256。请注意,我个人没有对此进行测试,甚至没有将其放入编译器中。但是,它应该让您对自己该怎么做有一个很好的了解。我强烈建议用这个测试边缘情况!

      #include <algorithm>
      
      bool check(const std::vector<int>& studs, 
      char* allowed, 
      unsigned int size){
      
          for(auto x : studs){
              if(std::find(allowed, allowed+size-1, x) == allowed+size-1 && x!= *(allowed+size))
                  return false;
          }
          return true;
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-05-04
        • 2020-07-03
        • 1970-01-01
        • 2019-11-12
        • 2016-03-13
        • 2011-12-16
        • 1970-01-01
        相关资源
        最近更新 更多