C++ Primer 学习笔记_37_STL实践与分析(11)--set类型

STL实践与分析

--set类型

引:

map容器是键-值对的集合,好比人名为键的地址和电话号码。相反的,set容器类型只是单纯的键的集合。当只想知道一个键是否存在时,使用set容器是最合适的。

除了两种例外情况,set容器支持大部分的map操作,包括下面几种:

1)第10.2节列出的所有通用的容器操作。

2)表10.3描述的构造函数。

3)表10.5描述的 insert操作。

4)表10.6描述的 count和 find操作。

5)表10.7描述的 erase操作。

两种例外包括:set不支持下标操作符,而且没有定义mapped_type类型。在set容器中,value_type不是pair类型,而是与key_type相同的类型。

一、set容器的定义和使用

与map容器一样,set容器的每个键都只对应一个元素。以一段范围的元素初始化set对象,或在set对象中插入一组元素时,对于每个键,事实上都只是添加了一个元素:

    vector<int> ivec;
    for (int i = 0;i != 10; ++i)
    {
        ivec.push_back(i);
        ivec.push_back(i);
    }

    set<int> iset(ivec.begin(),ivec.end());

    cout << "ivec: " << ivec.size() << endl;
    cout << "iset: " << iset.size() << endl;

1、在set中添加元素

可以使用insert操作在set容器中添加元素:

    set<string> strSet;
    strSet.insert("utile");
    strSet.insert("world");

    for (set<string>::iterator iter = strSet.begin(); iter != strSet.end(); ++iter)
    {
        cout << *iter << endl;
    }

另一种用法:在调用insert函数时,提供一对迭代器实参,插入其标记范围内的所有的元素。该版本的insert函数类似于形参为一对迭代器的构造函数–
对于一个键,仅仅插入一个元素:

    set<int> iSet;
    iSet.insert(ivec.begin(),ivec.end());

与map容器的操作一样,带有一个键参数的insert版本返回pair类型对象,包含一个迭代器和一个bool值,迭代器指向拥有该键的元素,而bool值则表明是否添加了元素。使用迭代器对的版本返回void类型。

2、从set中获取元素

set容器不提供下标操作符。为了通过键从set中获取元素,可使用find运算。如果只需简单地判断某个元素是否存在,同样可以使用count运算,返回set中该键对应的元素个数。当然,对于set容器,count的返回值只能是1(该元素存在)或0(该元素不存在):

    cout << iSet.count(1) << endl;
    cout << iSet.count(11) << endl;
    cout << *iSet.find(1) << endl;
    if (iSet.find(11) != iSet.end())
    {
        cout << *iSet.find(11) << endl;
    }

正如不能修改map中的元素的键部分一样,set中的键也为const。在获取指向set中某元素的迭代器之后,只能对其进行读操作:

    set<int>::iterator iter = iSet.find(1);
    *iter = 11;             //Error
    cout << *iter << endl;  //OK

二、创建“单词排除”集

第10.3.7节的程序从map对象 word_count中删除一个指定的单词。可将这个操作扩展为删除指定文件中所有的单词(即该文件记录的是排除集)。也即,我们的单词统计程序只对那些不在排除集中的单词进行统计:

void retricted_wc(ifstream &remove_file,map<string,int> &word_count)
{
    set<string> excluded;
    string remove_word;
    while (remove_file >> remove_word)
    {
        excluded.insert(remove_word);
    }

    string word;
    while (cin >> word)
    {
        if (excluded.find(word) == excluded.end())
        {
            word_count.insert(make_pair(word,1));
        }
    }
}
//原程序
void retricted_wc(ifstream &remove_file,map<string,int> &word_count)
{
    set<string> excluded;
    string remove_word;
    while (remove_file >> remove_word)
    {
        excluded.insert(remove_word);
    }

    string word;
    while (cin >> word)
    {
        if (!excluded.count(word))
        {
            ++ word_count[word];
        }
    }
}
//P321 习题10.24
int main()
{
    set<string> excluded;
    ifstream inFile("input");
    string excl_word;
    while (inFile >> excl_word)
    {
        excluded.insert(excl_word);
    }

    string word;
    while (cin >> word)
    {
        if (excluded.count(word))
        {
            cout << word << endl;
        }
        else
        {
            word.assign(word.begin(),word.end()-1);
            /**也可以使用
            *word.resize(word.size()-1);
            */
            cout << word << endl;
        }
    }
}
时间: 2024-10-05 22:29:30

C++ Primer 学习笔记_37_STL实践与分析(11)--set类型的相关文章

C++ Primer 学习笔记_45_STL实践与分析(19)--泛型算法的结构

STL实践与分析 --泛型算法的结构 引言: 正如全部的容器都建立在一致的设计模式上一样,算法也具有共同的设计基础. 算法最主要的性质是须要使用的迭代器种类.全部算法都指定了它的每一个迭代器形參可使用的迭代器类型.比方,假设形參必须为随机訪问迭代器则可提供vector或 deque类型的迭代器,或者提供指向数组的指针.而其它容器的迭代器不能用在这类算法上. C++还提供了另外两种算法模式:一种模式由算法所带的形參定义;还有一种模式则通过两种函数命名和重载的规范定义. 一.算法的形參模式 大多数的

C++ Primer 学习笔记_46_STL实践与分析(20)--容器特有的算法

STL实践与分析 --容器特有的算法 与其它顺序容器所支持的操作相比,标准库为list容器定义了更精细的操作集合,使它不必仅仅依赖于泛型操作.当中非常大的一个原因就是list容器不是依照内存中的顺序进行布局的,不支持随即訪问,这样,在list容器上就不能使用随即訪问迭代器的算法,如sort等:还有其它的一些算法如:merge.remove.reverse和unique,尽管能够用在list上,但却付出了高昂的性能代价.因此标准库结合list的内部结构,编写出了更快算法: list容器特有的操作

C++ Primer 学习笔记_35_STL实践与分析(9)--map种类(在)

STL实践与分析 --map类型(上) 引: map是键-值对的集合. map类型通常能够理解为关联数组:能够通过使用键作为下标来获取一个值,正如内置数组类型一样:而关联的本质在于元素的值与某个特定的键相关联,而并不是通过元素在容器中的位置来获取. 一.map对象的定义 1.定义map对象时,必须分别指明键和值的类型: map<string,int> wordCnt; map的构造函数 map<K,V>m; 创建一个名为m的空对象,其键和值的类型分别为K和V map<K,V&

C++ Primer 学习笔记_43_STL实践与分析(17)--再谈迭代器【中】

STL实践与分析 --再谈迭代器[中] 二.iostream迭代[续] 3.ostream_iterator对象和ostream_iterator对象的使用 能够使用ostream_iterator对象将一个值序列写入流中,其操作过程与使用迭代器将一组值逐个赋值给容器中的元素同样: ostream_iterator<string> out_iter(cout,"\n"); istream_iterator<string> in_iter(cin),eof; wh

C++ Primer 学习笔记_29_STL实践与分析(3) --操作步骤集装箱(下一个)

STL实践与分析 --顺序容器的操作(下) 六.訪问元素 假设容器非空,那么容器类型的front和back成员将返回容器的第一个和最后一个元素的引用. [与begin和end的对照:] 1)begin和end返回容器类型的迭代器,而不是引用: 2)end返回容器最后一个元素的下一个位置的迭代器,而back返回容器的最后一个元素的引用! /* *必须保证该list容器非空! *假设容器为空,则if语句内的全部操作都是没有定义的! */ if (!iList.empty()) { list<int>

C++ Primer 学习笔记_41_STL实践与分析(15)--先来看看算法【下一个】

STL实践与分析 --初窥算法[下] 一.写容器元素的算法 一些算法写入元素值.在使用这些算法写元素时一定要当心.必须确保算法所写的序列至少足以存储要写入的元素. 1.写入输入序列的元素 写入到输入序列的算法本质上是安全的--仅仅会写入与指定输入范围数量同样的元素. 写入到输入序列的一个简单算法是fill函数: fill(iVec.begin(),iVec.end(),10); fill(iVec.begin(),iVec.begin()+iVec.size()/2,0); fill带有一对迭代

C++ Primer 学习笔记_45_STL实践与分析(19)--建筑常规算法

STL实践与分析 --泛型算法的结构 引言: 正如全部的容器都建立在一致的设计模式上一样,算法也具有共同的设计基础. 算法最主要的性质是须要使用的迭代器种类.全部算法都指定了它的每一个迭代器形參可使用的迭代器类型. 比方,假设形參必须为随机訪问迭代器则可提供vector或 deque类型的迭代器,或者提供指向数组的指针. 而其它容器的迭代器不能用在这类算法上. C++还提供了另外两种算法模式:一种模式由算法所带的形參定义;还有一种模式则通过两种函数命名和重载的规范定义. 一.算法的形參模式 大多

C++ Primer 学习笔记_44_STL实践与分析(18)--再谈迭代器【下】

STL实践与分析 --再谈迭代器[下] 三.反向迭代器[续:习题] //P355 习题11.19 int main() { vector<int> iVec; for (vector<int>::size_type index = 0; index != 10; ++index) { iVec.push_back(index); } for (vector<int>::reverse_iterator r_iter = iVec.rbegin(); r_iter !=

C++ Primer 学习笔记_40_STL实践与分析(14)--概要、先来看看算法【上】

STL实践与分析 --概述.初窥算法[上] 标准库容器定义的操作很少.并没有给容器加入大量的功能函数.而是选择提供一组算法,这些算法大都不依赖特定的容器类型,是"泛型"的.可作用在不同类型的容器和不同类型的元素上! 所谓泛型算法:一是由于它们实现共同的操作,所以称之为"算法";而"泛型"指的是它们可以操作在多种容器类型上--不但可作用于vector或list这些标准库类型,还可用在内置数组类型.甚至其它类型的序列上,仅仅要自己定义的容器类型仅仅要