STL 集合类

set、multiset

概述

set 和 multiset 使得用户可以快速查找键(键是唯一存储在一维容器中的值)。二者区别:set只能存储唯一的值,multiset能存储重复值

set 和 multiset 的通过实现类似二叉树的内部结构进行排序,提高了查找速度。因此,这两种结构的特定位置元素不能被替换为值不同的新元素。

注意包含头文件:#include <set>

实例化

/*
desc:set/multiset的初始化
*/
#include <iostream>
#include <set>
using namespace std;

//指定排序标准
template <typename T>
struct SordDescending
{
    bool operator() (const &T lsh, const &T rsh) const
    {
        return lsh > rsh;
    }
};

int main()
{
    // 1. 简单初始化(此时的默认排序谓词为:std::less<T>。升序为std::greater<T>)
    set <int> setIntegers1;
    multiset <int> mulsetIntegers1;

    // 2. 带有用户自定义排序谓词的初始化
    set <int, SordDescending<int>> setIntegers2;
    multiset <int, SordDescending<int>> mulsetIntegers2;

    // 3. 用另一个容器(或者该容器的一部分)来初始化
    set <int> setIntegers3(setIntegers1);
    multiset <int> mulsetIntegers(setIntegers1.cbegin(), setIntegers1.end());
    system("pause");
    return 0;
}

插入

#include <iostream>
#include <set>
using namespace std;

template <typename T>
void DisplayElement (const T& input)
{
    for (auto iElementLocator = input.cbegin()
        ; iElementLocator != input.cend()
        ; ++iElementLocator)
    {
        cout << *iElementLocator << " "; 
    }
    cout << endl;
}

int main()
{
    set <int> setIntegers;
    multiset <int> msetIntegers;

    setIntegers.insert(60);
    setIntegers.insert(-1);
    setIntegers.insert(3000);
    DisplayElement(setIntegers);
    setIntegers.insert(3000);
    cout << "Inserting the number 3000 again:" << endl;
    DisplayElement(setIntegers);

    msetIntegers.insert(setIntegers.begin(), setIntegers.end());
    DisplayElement(msetIntegers);

    msetIntegers.insert(3000);
    cout << "The count of'3000' in multiset is: ";
    cout << msetIntegers.count(3000) << endl;
    system("pause");
    return 0;
}

务必使用 multiset.count(value) 来确定有多少个元素包含特定的value值

查找

#include <set>
#include <iostream>
using namespace std;

int main()
{
    //43 78 -1 124
    set <int> setIntegers;
    setIntegers.insert(43);
    setIntegers.insert(78);
    setIntegers.insert(-1);
    setIntegers.insert(124);
    for (auto iElement = setIntegers.begin(); iElement != setIntegers.end(); ++iElement)
    {
        cout << *iElement << " ";
    }
    cout << endl;

    //通过成员函数:find()查找 
    auto iElementFound = setIntegers.find(1223); 
    if (iElementFound != setIntegers.end()) //实参可以换成set中存在的
    {
        cout << "Element " << *iElementFound << " found!" << endl;
    }
    else
    {
        cout << "Element not found in set!" << endl;
    }
    system("pause");
    return 0;
}

find() 返回一个迭代器,指向找到的第一个元素。可将该迭代器递增以获取下一个元素。

删除

/*
通过成员函数:erase()
    1. setObject.erase (key); // 根据键删除值
    
    2. setObject.erase (element); // 迭代器作为参数,并删除该迭代器指向的对象
    MSETINT::iterator elementFound = msetInts.find(numberToErase); 
    if (elementFound != msetInts.end ()) 
        msetInts.erase (elementFound); 
    else 
        cout << "Element not found!" << endl; 

    3. setObject.erase (iLowerBound, iUpperBound); // 迭代器指定删除的边界
    MSETINT::iterator elementFound = msetInts.find(valueToErase); 
    if (elementFound != msetInts.end ()) 
        msetInts.erase (msetInts.begin (), elementFound);
*/
#include <set>
#include <iostream>
using namespace std;

template <typename T>
void DisplayElement (const T& input)
{
    for (auto iElement = input.cbegin()
        ; iElement != input.cend()
        ; ++iElement)
    {
        cout << *iElement << " ";
    }
    cout << endl;
}
typedef multiset <int> MSETINT;

int main()
{
    MSETINT msetIntegers;
    msetIntegers.insert(43);
    msetIntegers.insert(78);
    msetIntegers.insert(78);
    msetIntegers.insert(49);
    msetIntegers.insert(124);

    cout << "multiset contains " << msetIntegers.size() << " elements.";
    cout << " These are: " << endl;
    DisplayElement(msetIntegers);

    cout << "Please enter a number to be erased from the set" << endl;
    int nNumberToErase = 0;
    cin >> nNumberToErase;

    cout << "Erasing " << msetIntegers.count(nNumberToErase);
    cout << " instances of value " << nNumberToErase << endl;
    msetIntegers.erase(nNumberToErase);

    cout << "multiset contains " << msetIntegers.size() << " elements: ";
    DisplayElement(msetIntegers);
    system("pause");
    return 0;
}

通过 size() 指出容器包含多少个元素。

一个具体例子:存储对象的set(multiset)

#include <set>
#include <string>
#include <iostream>
using namespace std;

template <typename T>
void DisplayContents (const T& input)
{
    for (auto iElement = input.cbegin()
        ; iElement != input.cend()
        ; ++iElement)
    {
        cout << *iElement << endl;
    }
    cout << endl;
}

struct ContactItem
{
    string strContactsName;
    string strPhoneNumber;
    string strDisplayRepresentation;

    ContactItem (const string& strName, const string& strNumber)
    {
        strContactsName = strName;
        strPhoneNumber = strNumber;
        strDisplayRepresentation = (strContactsName + ": " + strPhoneNumber);
    }
    bool operator == (const ContactItem& itemToCompare) const
    {
        return (itemToCompare.strContactsName == this->strContactsName);
    }
    bool operator < (const ContactItem& itemToCompare) const
    {
        return (this->strContactsName < itemToCompare.strContactsName);
    }
    operator const char*() const
    {
        return strDisplayRepresentation.c_str();
    }
};
int main()
{
    set <ContactItem> setContacts;
    setContacts.insert(ContactItem("Jack Welsch", "+1 7889 879 879"));
    setContacts.insert(ContactItem("Bill Gates", "+1 97 7897 8799 8"));
    setContacts.insert(ContactItem("Angi Merkel", "+49 23456 5466")); 
    setContacts.insert(ContactItem("Vlad Putin", "+7 6645 4564 797")); 
    setContacts.insert(ContactItem("John Travolta", "91 234 4564 789")); 
    setContacts.insert(ContactItem("Ben Affleck", "+1 745 641 314"));
    DisplayContents(setContacts);

    cout << "Enter a person whose number you wish to delete: " ;
    string deletename;
    getline(cin, deletename);

    auto iContactFound = setContacts.find(ContactItem(deletename, ""));
    if (iContactFound != setContacts.end())
    {
        setContacts.erase(iContactFound);
        cout << "After deleting: " << endl;
        DisplayContents(setContacts);
    }
    else
    {
        cout << "Contact not found!" << endl;
    }
    system("pause");
    return 0;
}

对于存储对象的set、multiset,一定要实现运算符 < 和 ==,前者用于排序,后者用于 set::find()


unordered_set、unordered_multiset

通过hash函数计算排序索引,根据索引决定将元素放到哪个桶(bucket)内。

使用时注意添加头文件:#include <unordered_set>

对于初始化、插入、查找、删除等操作与set类似,注意一个重要特征:

负责确定排列顺序的散列函数:

unordered_set<int>::hasher HFn = usetInt.hash_function(); 

一个具体例子:

#include <iostream>
#include <unordered_set>
using namespace std;
template <typename T>
void DisplayContents (const T& input)
{
    cout << "Number of elements, size() = " << input.size() << endl;
    cout << "Max bucket count = " << input.max_bucket_count() << endl;
    cout << "Load factor: " << input.load_factor() << endl;
    cout << "Max load factor = " << input.max_load_factor() << endl;
    cout << "Unordered set contains: " << endl;

    for (auto iElement = input.cbegin()
        ; iElement != input.cend()
        ; ++iElement)
    {
        cout << *iElement << " ";
    }
    cout << endl;
}

int main()
{
    unordered_set <int> usetIntegers;
    cout << usetIntegers.max_bucket_count() << endl;
    cout << endl;
    usetIntegers.insert(1000);
    usetIntegers.insert(-3);
    usetIntegers.insert(2011);
    usetIntegers.insert(300);
    usetIntegers.insert(-1000);
    usetIntegers.insert(989);
    usetIntegers.insert(-300);
    usetIntegers.insert(111);
    DisplayContents(usetIntegers);
    usetIntegers.insert(999);
    cout << endl;
    cout << usetIntegers.max_bucket_count() << endl;
    cout << endl;
    DisplayContents(usetIntegers);

    cout << "Enter int you want to check for existence in set: ";
    int Key = 0;
    cin >> Key;
    auto iPairThousand = usetIntegers.find(Key);

    if (iPairThousand != usetIntegers.cend())
    {
        cout << *iPairThousand << " found in set" << endl;
    }
    else
    {
        cout << Key << " not available in set" << endl;
    }
    system("pause");
    return 0;
}
### C++ STL 集合的使用方法和类型 #### 1. **STL集合概述** C++标准模板库(Standard Template Library, STL)提供了多种容器来存储数据,其中集合类容器用于管理一组对象。这些容器具有不同的特性以适应各种需求。 常见的集合类容器有 `vector`、`list`、`set`、`map` 等[^1]。每种容器都有其特定的功能和适用场景。 --- #### 2. **常用集合类型及其特点** ##### (1) **Vector** - 动态数组实现。 - 支持随机访问,效率高。 - 插入删除操作较慢(特别是在中间位置插入或删除时需移动大量元素)。 ```cpp #include <vector> std::vector<int> vec; vec.push_back(10); // 添加元素到末尾 ``` ##### (2) **List** - 双向链表结构。 - 不支持随机访问。 - 插入删除速度快(无需移动其他元素)。 ```cpp #include <list> std::list<int> lst; lst.push_back(10); // 尾部添加元素 lst.push_front(5); // 头部添加元素 ``` ##### (3) **Set** - 基于红黑树实现。 - 存储唯一键值,自动排序。 - 提供高效的查找、插入和删除操作。 ```cpp #include <set> std::set<int> st; st.insert(10); for(auto it = st.begin(); it != st.end(); ++it){ std::cout << *it << " "; // 迭代器遍历 } ``` 上述代码展示了如何通过迭代器访问 `set` 容器中的元素[^3]。 ##### (4) **Map** - 键值对映射关系。 - 自动按关键字排序。 - 查找速度较快。 ```cpp #include <map> std::map<std::string, int> mp; mp["apple"] = 5; // 插入键值对 if(mp.find("banana") != mp.end()){ std::cout << "Key exists"; } else { std::cout << "Key does not exist"; } ``` --- #### 3. **集合的操作方法** 以下是几种常见集合的操作: - **插入**: 向集合中添加新元素。 - **删除**: 移除指定元素。 - **查找**: 判断某个元素是否存在。 - **遍历**: 访问集合内的所有元素。 对于 `set` 和 `map`,可以利用迭代器完成高效遍历。 --- #### 4. **性能分析** 不同类型的集合适用于不同的应用场景。例如: - 如果需要频繁地在列表两端进行增删操作,则应优先考虑 `list`。 - 若更关注快速定位某项数值的位置或者保持有序状态,则可以选择 `set` 或者 `map`[^2]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值