C++ STL一一set和multiset

来源:互联网 发布:4g电话软件 编辑:程序博客网 时间:2024/05/19 15:20

一、特点

set和multiset会根据特定的排序准则,自动将元素排序。两者不同之处在于multiset允许元素重复而set不允许。

二、构造和析构

set c //产生一个空的set/multiset,其中不含任何元素set c(op) //以op为排序准则,产生一个空的set/multisetset c1(c2) //产生某个set/multiset的副本,所有元素均被复制set c(beg,end) //以区间[beg,end]内的元素产生一个set/multisetset c(beg,end,op) //以op为准则,利用区间[beg,end]内的元素产生一个set/multisetc.~set() //销毁所有元素,释放内存
其中set可为下列形式

set<Elem> //一个set,以less<>(operator<)为准则排序set<Elem,op> //一个set,以op为准则排序multiset<Elem> //一个multiset,以less<>(operator<)为准则排序multiset<Elem,op> //一个multiset,以op为准则排序
三、定义排序准则

1.以template参数定义

特点:只有排序准则相同的容器才能被合并

std::set<int,std::greater<int>> coll;

具体示例如下:

#include <iostream>#include <string>#include <deque>#include <set>#include <algorithm>using namespace std;/* class Person */class Person {  private:    string fn;    // first name    string ln;    // last name  public:    Person() {    }    Person(const string& f, const string& n)     : fn(f), ln(n) {    }    string firstname() const;    string lastname() const;    // ...};inline string Person::firstname() const {    return fn;}inline string Person::lastname() const {    return ln;}ostream& operator<< (ostream& s, const Person& p){    s << "[" << p.firstname() << " " << p.lastname() << "]";    return s;}/* class for function predicate * - operator () returns whether a person is less than another person */class PersonSortCriterion {  public:    bool operator() (const Person& p1, const Person& p2) const {        /* a person is less than another person         * - if the last name is less         * - if the last name is equal and the first name is less         */        return p1.lastname()<p2.lastname() ||               (p1.lastname()==p2.lastname() &&                p1.firstname()<p2.firstname());    }};int main(){    Person p1("nicolai","josuttis");    Person p2("ulli","josuttis");    Person p3("anica","josuttis");    Person p4("lucas","josuttis");    Person p5("lucas","otto");    Person p6("lucas","arm");    Person p7("anica","holle");        // declare set type with special sorting criterion    typedef set<Person,PersonSortCriterion> PersonSet;    // create such a collection    PersonSet coll;    coll.insert(p1);    coll.insert(p2);    coll.insert(p3);    coll.insert(p4);    coll.insert(p5);    coll.insert(p6);    coll.insert(p7);    // do something with the elements    // - in this case: output them    cout << "set:" << endl;    PersonSet::iterator pos;    for (pos = coll.begin(); pos != coll.end(); ++pos) {        cout << *pos << endl;    }}

2.以构造函数参数定义

特点:同一个型别可以运用不同的排序准则,而排序准则的初始值或状态也可以不同。如果执行期才获得排序准则,并且需要用到不同的排序准则(但数据型别必须相同)

实例如下:

//print.h#include <iostream>/* PRINT_ELEMENTS() * - prints optional C-string optcstr followed by * - all elements of the collection coll * - separated by spaces */template <class T>inline void PRINT_ELEMENTS (const T& coll, const char* optcstr=""){    typename T::const_iterator pos;    std::cout << optcstr;    for (pos=coll.begin(); pos!=coll.end(); ++pos) {        std::cout << *pos << ' ';    }    std::cout << std::endl;}
#include <iostream>#include <set>#include "print.h"using namespace std;// type for sorting criteriontemplate <class T>class RuntimeCmp {public:enum cmp_mode {normal, reverse};private:cmp_mode mode;public:  // constructor for sorting criterion// - default criterion uses value normalRuntimeCmp (cmp_mode m=normal) : mode(m) {}// comparison of elementsbool operator() (const T& t1, const T& t2) const {return mode == normal ? t1 < t2 : t2 < t1;}// comparison of sorting criteriabool operator== (const RuntimeCmp& rc) {return mode == rc.mode;}};// type of a set that uses this sorting criteriontypedef set<int,RuntimeCmp<int> > IntSet;// forward declarationvoid fill (IntSet& set);int main(){// create, fill, and print set with normal element order// - uses default sorting criterionIntSet coll1;fill(coll1);PRINT_ELEMENTS (coll1, "coll1: ");// create sorting criterion with reverse element orderRuntimeCmp<int> reverse_order(RuntimeCmp<int>::reverse);// create, fill, and print set with reverse element orderIntSet coll2(reverse_order);fill(coll2);PRINT_ELEMENTS (coll2, "coll2: ");// assign elements AND sorting criterioncoll1 = coll2;coll1.insert(3);PRINT_ELEMENTS (coll1, "coll1: ");// just to make sure...if (coll1.value_comp() == coll2.value_comp()) {cout << "coll1 and coll2 have same sorting criterion"<< endl;}else {cout << "coll1 and coll2 have different sorting criterion"<< endl;}}void fill (IntSet& set){// fill insert elements in random orderset.insert(4);set.insert(7);set.insert(5);set.insert(1);set.insert(6);set.insert(2);set.insert(5);}
四、非变动性操作

用来查询大小、相互比较

c.size()   //返回当前元素数量  c.empty()  //判断大小是否为0  c.max_size() //返回可容纳的元素最大数量  

五、特殊的搜寻函数
count(elem) //返回元素值为elem的元素个数find(elem) //返回元素值为elem的第一个元素,如果找不到就返回end()lower_bound(elem) //返回elem的第一个可安插位置,也就是“元素值>=elem”的第一个元素位置upper_bound(elem) //返回elem的最后一个可安插位置,也就是“元素值>elem”的第一个元素位置equal_range(elem) //返回elem可安插的第一个位置和最后一个位置,也就是“元素值==elem”的元素区间
运行实例:

#include <iostream>#include <set>using namespace std;int main (){set<int> c;c.insert(1);c.insert(2);c.insert(4);c.insert(5);c.insert(6);set<int>::iterator it = c.begin();while (it != c.end()){cout<<*it++<<' ';}cout<<endl;cout << "lower_bound(3): " << *c.lower_bound(3) << endl;cout << "upper_bound(3): " << *c.upper_bound(3) << endl;cout << "equal_range(3): " << *c.equal_range(3).first << " "<< *c.equal_range(3).second << endl;cout << endl;cout << "lower_bound(5): " << *c.lower_bound(5) << endl;cout << "upper_bound(5): " << *c.upper_bound(5) << endl;cout << "equal_range(5): " << *c.equal_range(5).first << " "<< *c.equal_range(5).second << endl;}

六、赋值操作

c1 = c2  //将c2的元素全部赋值给c1   c1.swap(c2);  swap(c1,c2);  
七、迭代器
c.begin() //返回一个随机存取迭代器,指向第一个元素  c.end()   //返回一个随机存取迭代器,指向最后元素的下一位置  c.rbegin() //返回一个逆向迭代器,指向逆向迭代的第一个元素  c.rend()    //返回一个逆向迭代器,指向逆向迭代的最后元素的下一位置  
八、安插和移除
c.insert(elem) //安插一份elem副本,返回新元素位置c.insert(pos,elem) //安插一份elem副本,返回新元素位置(pos是个提示,指出安插操作的搜寻七点)c.insert(beg,end) //将区间[beg,end]内所有元素的副本安插到c(无返回值)c.erase(elem) //移除“与elem相等”的所有元素,返回被移除的元素个数c.erase(pos) //移除迭代器pos所在位置上的元素(无返回值)c.erase(beg,end) //移除区间[beg,end]内的所有元素,无返回值c.clear() //移除全部元素,将整个容器清空
注意:安插函数的返回值不同
1.set提供如下接口:

pair<iterator,bool> insert(const value_type& elem);iterator insert(iterator pos_hint,const value_type& elem);

2.multiset提供如下接口:

iterator insert(const value_type& elem);iterator insert(iterator pos_hint,const value_type& elem);
返回值不同的原因:因为multiset允许元素重复,而set不允许,所以需要pair对来进行组织判断:

pair中的second用来表示安插是否成功

pair中的first成员返回新元素位置或返回现存的同值元素的位置(如果set已含同值元素)。

九、运行实例

#include <iostream>#include <set>#include <algorithm>#include <iterator>using namespace std;int main(){    /* type of the collection:     * - no duplicates     * - elements are integral values     * - descending order     */    typedef set<int,greater<int> > IntSet;    IntSet coll1;        // empty set container    // insert elements in random order    coll1.insert(4);    coll1.insert(3);    coll1.insert(5);    coll1.insert(1);    coll1.insert(6);    coll1.insert(2);    coll1.insert(5);    // iterate over all elements and print them    IntSet::iterator pos;    for (pos = coll1.begin(); pos != coll1.end(); ++pos) {        cout << *pos << ' ';    }    cout << endl;    // insert 4 again and process return value    pair<IntSet::iterator,bool> status = coll1.insert(4);    if (status.second) {        cout << "4 inserted as element "             << distance(coll1.begin(),status.first) + 1             << endl;    }    else {        cout << "4 already exists" << endl;    }    // assign elements to another set with ascending order    set<int> coll2(coll1.begin(),                   coll1.end());        // print all elements of the copy    copy (coll2.begin(), coll2.end(),          ostream_iterator<int>(cout," "));    cout << endl;    // remove all elements up to element with value 3    coll2.erase (coll2.begin(), coll2.find(3));    // remove all elements with value 5    int num;    num = coll2.erase (5);    cout << num << " element(s) removed" << endl;    // print all elements    copy (coll2.begin(), coll2.end(),          ostream_iterator<int>(cout," "));    cout << endl;}
如果是multiset,则只需做稍微改动:

#include <iostream>#include <set>#include <algorithm>#include <iterator>using namespace std;int main(){    /* type of the collection:     * - duplicates allowed     * - elements are integral values     * - descending order     */    typedef multiset<int,greater<int> > IntSet;    IntSet coll1;        // empty multiset container    // insert elements in random order    coll1.insert(4);    coll1.insert(3);    coll1.insert(5);    coll1.insert(1);    coll1.insert(6);    coll1.insert(2);    coll1.insert(5);    // iterate over all elements and print them    IntSet::iterator pos;    for (pos = coll1.begin(); pos != coll1.end(); ++pos) {        cout << *pos << ' ';    }    cout << endl;    // insert 4 again and process return value    IntSet::iterator ipos = coll1.insert(4);    cout << "4 inserted as element "         << distance(coll1.begin(),ipos) + 1 << endl;    // assign elements to another multiset with ascending order    multiset<int> coll2(coll1.begin(),                        coll1.end());        // print all elements of the copy    copy (coll2.begin(), coll2.end(),          ostream_iterator<int>(cout," "));    cout << endl;    // remove all elements up to element with value 3    coll2.erase (coll2.begin(), coll2.find(3));    // remove all elements with value 5    int num;    num = coll2.erase (5);    cout << num << " element(s) removed" << endl;    // print all elements    copy (coll2.begin(), coll2.end(),          ostream_iterator<int>(cout," "));    cout << endl;}