【问题标题】:Using set_union for strings对字符串使用 set_union
【发布时间】:2019-12-21 03:40:43
【问题描述】:

我有两个向量,我需要它们在第三个向量中的并集(不指定第三个向量的大小)

std::vector<std::string> a = {"a","b"};
std::vector<std::string> b = {"d","c"};

std::vector<std::string> c;

std::set_union(a.begin(),a.end(),b.begin(),b.end(),c.begin());
std::cout<<c[1];

这会编译,但输出为空。

【问题讨论】:

    标签: c++ algorithm sorting vector stl


    【解决方案1】:

    算法std::set_union 需要有序序列。 在您的字符串示例中,第一个向量按升序排列,第二个向量按降序排列。

    此外,向量c 是空的,因此您不能在算法调用中使用表达式c.begin()。您需要使用std::back_insert_iterator

    对于您的字符串示例,算法的调用可能如下所示,如演示程序中所示。

    #include <iostream>
    #include <string>
    #include <vector>
    #include <iterator>
    #include <algorithm>
    
    
    int main() 
    {
        std::vector<std::string> a = { "a", "b" };
        std::vector<std::string> b = { "d", "c" };
    
        std::vector<std::string> c;
    
        std::set_union( std::begin( a ), std::end( a ), 
                        std::rbegin( b ), std::rend( b ),
                        std::back_inserter( c ) );
    
        for ( const auto &s : c ) std::cout << s << ' ';
        std::cout << '\n';
    
        return 0;
    }
    

    它的输出是

    a b c d 
    

    否则需要对向量进行排序。

    如果您可能无法对原始向量进行排序,那么您可以使用以下方法

    #include <iostream>
    #include <string>
    #include <vector>
    #include <iterator>
    #include <algorithm>
    
    
    int main() 
    {
        std::vector<std::string> a = { "a", "b" };
        std::vector<std::string> b = { "d", "c", "a" };
    
        std::vector<std::string> c( a );
        c.insert( std::end( c ), std::begin( b ), std::end( b ) );
    
        std::sort( std::begin( c ), std::end( c ) );
    
        c.erase( std::unique( std::begin( c ), std::end( c ) ), std::end( c ) );
    
        for ( const auto &s : c ) std::cout << s << ' ';
        std::cout << '\n';
    
        return 0;
    }
    

    程序输出是

    a b c d
    

    【讨论】:

    • 谢谢!不过,它似乎也适用于未排序的输入向量。
    【解决方案2】:

    您的代码有两个问题:

    1. 您没有阅读 std::set_union 的要求 - 输入范围必须根据给定的比较函数(在您的情况下为 operator&lt;)进行排序 - 这不适用于 b
    2. 算法无法通过c.begin()调整c的大小;它仍然是空的,你写的越界。使用std::back_insert_iterator

    【讨论】:

      【解决方案3】:

      使用std::set_union() 算法的替代方法是使用std::setstd::unordered_set 容器来存储两个向量的所有元素,然后从该容器初始化结果向量。

      这种方法的缺点是额外的容器需要两个向量中唯一元素数量的线性空间。

      您使用哪个容器,将取决于您是否需要对结果向量进行排序。如果您不需要对结果向量进行排序,则可以使用std::unordered_set

      std::vector<std::string> make_unsorted_union(const std::vector<std::string>& a,
                                                   const std::vector<std::string>& b)
      {
         std::unordered_set<std::string> st;
      
         for (auto& str: a)
            st.insert(str);
      
         for (auto& str: b)
            st.insert(str);
      
         return std::vector<std::string>(st.begin(), st.end());
      }
      

      将元素插入std::unordered_set 平均可以在恒定时间内完成。

      如果您需要对结果向量进行排序,则可以使用 std::set 代替:

      std::vector<std::string> make_sorted_union(const std::vector<std::string>& a,
                                                  const std::vector<std::string>& b)
      {
         std::set<std::string> st;
      
         for (auto& str: a)
            st.insert(str);
      
         for (auto& str: b)
            st.insert(str);
      
         return std::vector<std::string>(st.begin(), st.end());
      }
      

      这些函数可以按如下方式使用:

      int main() {
         std::vector<std::string> a = {"a", "z", "z", "b", "z"};
         std::vector<std::string> b = {"d", "v", "c", "x", "e"};
      
         std::vector<std::string> c = make_unsorted_union(a, b);
      
         for (auto& str: c)
            std::cout << str << ' ';
         std::cout << '\n';
      
         c = make_sorted_union(a, b);
      
         for (auto& str: c)
            std::cout << str << ' ';
         std::cout << '\n';
      }
      

      我这个程序的输出是:

      e c x b v d z a 
      a b c d e v x z 
      

      【讨论】:

        猜你喜欢
        • 2020-01-25
        • 2017-12-07
        • 1970-01-01
        • 2017-01-17
        • 1970-01-01
        • 1970-01-01
        • 2017-06-20
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多