在 C++ 中查詢集合交集

Jinku Hu 2023年1月30日 2021年1月4日
  1. 使用 std::set_intersection 方法在 C++ 中尋找集合交集
  2. 使用 std::set_symmetric_difference 方法在 C++ 中查詢集合對稱差異
在 C++ 中查詢集合交集

本文將為大家講解幾種在 C++ 中如何尋找集合交集的方法。

使用 std::set_intersection 方法在 C++ 中尋找集合交集

std::set_intersection 方法是 C++ 演算法庫的一部分,它包含在 <algorithm> 頭中。set_intersection 演算法操作並不侷限於 std::set 物件,而是可以處理任何基於範圍的物件,例如 std::vector。需要注意的是,兩個輸入範圍在傳遞給 set_intersection 演算法之前必須進行排序。

在下面的例子中,我們宣告兩個 std::set 變數,並用任意 string 型別的元素初始化它們。set_intersection 函式的前四個引數是對應物件的範圍迭代器,第五個引數是儲存計算出的交集的範圍的開始。在這種情況下,我們宣告一個 std::vector 來存放這些元素。

#include <iostream>
#include <vector>
#include <string>
#include <set>
#include <algorithm>

using std::cout; using std::endl;
using std::cin; using std::string;
using std::set; using std::vector;

template<typename T>
void printVectorElements(vector<T> &vec)
{
    cout << "{ ";
    for (const auto &item : vec) {
        cout << item << ", ";
    }
    cout << "\b\b }" << endl;
}

int main() {
    set<string> s1 {"array", "vector",
                    "deque", "list",
                    "set", "map",
                    "multimap", "span"};
    set<string> s2(s1);
    s2.insert("stack");
    s2.insert("queue");

    vector<string> s1s2_intsec;

    std::set_intersection(s1.begin(), s1.end(),
                          s2.begin(), s2.end(),
                          std::back_inserter(s1s2_intsec));

    cout << "s1 ∩ s2: ";
    printVectorElements(s1s2_intsec);

    exit(EXIT_SUCCESS);
}

輸出:

s1 ∩ s2: ( array, deque, list, map, multimap, set, span, vector )

儘管 std::set_intersection 儲存了使用者指定的交集元素,但它不能是與輸入範圍重疊的範圍。另一個需要注意的重要點是指定目標範圍,它有足夠的空間來儲存交叉元素。靈活的方法是使用動態陣列 std::vector,並使用 std::back_inserter 方法將元素推送到物件中。如果你指定 vector.begin() 迭代器時沒有預留記憶體作為目的引數,演算法可能會丟擲一個分段故障。下一個例子演示了 vector 物件上的 set_intersection 方法。

#include <iostream>
#include <vector>
#include <string>
#include <set>
#include <algorithm>

using std::cout; using std::endl;
using std::cin; using std::string;
using std::set; using std::vector;

template<typename T>
void printVectorElements(vector<T> &vec)
{
    cout << "{ ";
    for (const auto &item : vec) {
        cout << item << ", ";
    }
    cout << "\b\b }" << endl;
}

int main() {
    vector<int> v1v2_intsec;
    vector<int> v1 {9,7,5,1,2};
    vector<int> v2 {4,3,2,1,7,8};
    std::sort(v1.begin(), v1.end());
    std::sort(v2.begin(), v2.end());

    std::set_intersection(v1.begin(), v1.end(),
                          v2.begin(), v2.end(),
                          std::back_inserter(v1v2_intsec));
    cout << "v1 ∩ v2: ";
    printVectorElements(v1v2_intsec);

    exit(EXIT_SUCCESS);
}

輸出:

v1 ∩ v2: ( 1, 2, 7 )

使用 std::set_symmetric_difference 方法在 C++ 中查詢集合對稱差異

另一個來自 C++ 標準庫的演算法是 std::set_symmetric_difference,它搜尋只在其中一個輸入範圍內找到的元素。函式引數與 std::set_intersection 方法類似。兩種演算法都採取排序的範圍,並將找到的元素也以排序的方式儲存。注意,std::set 容器預設包含排序元素。因此,它可以直接作為輸入範圍傳遞。而 std::vector 內容在被 std::set_symmetric_difference 處理之前必須明確地進行排序。

#include <iostream>
#include <vector>
#include <string>
#include <set>
#include <algorithm>

using std::cout; using std::endl;
using std::cin; using std::string;
using std::set; using std::vector;

template<typename T>
void printVectorElements(vector<T> &vec)
{
    cout << "{ ";
    for (const auto &item : vec) {
        cout << item << ", ";
    }
    cout << "\b\b }" << endl;
}

int main() {
    vector<int> v1 {9,7,5,1,2};
    vector<int> v2 {4,3,2,1,7,8};
    std::sort(v1.begin(), v1.end());
    std::sort(v2.begin(), v2.end());

    vector<int> v1v2_symdif;
    std::set_symmetric_difference(v1.begin(), v1.end(),
                          v2.begin(), v2.end(),
                          std::back_inserter(v1v2_symdif));
    cout << "v1 △ v2: ";
    printVectorElements(v1v2_symdif);

    exit(EXIT_SUCCESS);
}

輸出:

v1 △ v2: ( 3, 4, 5, 8, 9 )
Author: Jinku Hu
Jinku Hu avatar Jinku Hu avatar

Founder of DelftStack.com. Jinku has worked in the robotics and automotive industries for over 8 years. He sharpened his coding skills when he needed to do the automatic testing, data collection from remote servers and report creation from the endurance test. He is from an electrical/electronics engineering background but has expanded his interest to embedded electronics, embedded programming and front-/back-end programming.

LinkedIn

相關文章 - C++ Set