C++ STL(容器:list&set)

目录

0list

1list的API 

2set/multiset

 关于对组(pair)

set不允许插入相同的值 

从大到小排序

插入自定义类型


0list

双向链表,数据由两个部分组成,一个数据域一个指针域

优缺点: 

  • 采用动态存储分配,不会造成内存浪费和溢出
  • 链表执行插入和删除操作十分方便,修改指针即可
  • 链表灵活,但是空间和时间额外耗费较大

迭代器:bidirectional Iterators

List有一个重要性质,插入操作和删除操作都不会造成原有的迭代器的list迭代器的失效。

这在vector是不成立的,因为vector的插入操作可能造成记忆体重新配置,导致原有的迭代器全部失效,甚至list元素的删除,也只

有被删除元素的迭代器失效,其他迭代器不受任何影响。

头指针

#include<list>
using namespace std;

1list的API 

list<DataType>listT;//list采用模板类实现,对象的默认构造函数
list(beg,end);//构造函数将(beg,end)区间中的元素拷贝给本身
list(n,len);//构造函数将n个elen拷贝给本身
list(const list & Lst);//拷贝构造函数


push_back(elen);//在容器尾部加入一个元素
pop_back();//删除容器中最后一个元素
push_front(elen);//在容器开头插入一个元素

pop_front();//从容器开头移除第一个元素
insert(pos,elen);//在pos位置插入elen元素的拷贝,返回新数据的位置
insert(pos,n,elen);//在pos位置插入n个elen数据,无返回值
insert(pos,beg,end);//在pos位置插入【beg,end】,无返回值
clear();//清空
erase(beg,end);//删除【beg,end】区间的数据,返回下一个数据的位置
erase(pos);//删除pos位置的数据,返回下一个数据的位置
remove(elen);//删除容器中所有与elen值匹配的元素
    list<int>L(10,10);
    list<int>L2(L.begin(),L.end());

    PrintList(L);
    PrintList(L2);

    list<int>L3;
    L3.push_back(10);
    L3.push_back(30);
    L3.push_back(50);

    L3.push_front(100);
    L3.push_front(300);
    L3.push_front(500);

    PrintList(L3);
    Reverse_PrintList(L3);

    //删除两端数据
    L3.pop_front();
    L3.pop_back();
    PrintList(L3);

    L3.insert(L3.begin(),1000);//在开始位置插入1000
    PrintList(L3);

    L3.remove(300);
    PrintList(L3);

其中,打印和逆序打印,接口如下:

void PrintList(list<int> L)
{
    qDebug()<<"进入遍历:";
    for(list<int>::iterator it = L.begin();it != L.end();it++)
    {
        qDebug()<<*it;
    }

}
void Reverse_PrintList(list<int> L)
{
    qDebug()<<"进入逆序遍历:";
    for(list<int>::reverse_iterator it = L.rbegin();it != L.rend();it++)
    {
        qDebug()<<*it;
    }

}

程序输出:

size();//返回容器中的元素个数
empty();//判断容器是否为空
resize(num);//重新指定容器长度为num
resize(num,elen);//重新制定list长度为num,如果变长,多余部分用elen补充

assign(beg,end);//将【beg,end】区间中的数据拷贝给本身
assign(n,elen);//将n个elen拷贝给赋值本身
list & operator=(const list & lst);//重载等号运算符
swap(lst);//将list和本身元素交换

front();//返回第一个元素
back();//返回最后一个元素

 具体操作:

    qDebug()<<"L3大小:"<<L3.size();

    L3.resize(10,0);
    PrintList(L3);

    list<int>L4;
    L4.assign(L3.begin(),L3.end());
    PrintList(L4);

reverse();//反转链表
sort();//排序
    list<int>L5;
    L5.push_back(1);
    L5.push_back(3);
    L5.push_back(5);
    L5.push_back(7);
    L5.push_back(9);
    PrintList(L5);
    L5.reverse();
    PrintList(L5);

    list<int>L6;
    L6.push_back(1);
    L6.push_back(3);
    L6.push_back(2);
    L6.push_back(5);
    L6.push_back(7);
    PrintList(L6);
    L6.sort();
    PrintList(L6);

2set/multiset

set/multiset的特性是所有元素会根据元素的值自动进行排序

set/multiset以红黑树为底层机制,其查找效率非常好,set容器中不允许重复的元素,multiset则允许重复元素存在

set<T> st;// 默认构造函数
multiset<T> mst;// multiset默认构造函数
set(const set &st);// 拷贝构造函数

set &operator=(const set &st);	// 重载等号运算符
swap(st);// 交换两个集合容器中的元素

size();// 返回容器中元素的数目
empty();// 判断容器是否为空

insert(elem);// 在容器中插入元素
clear();// 清空所有元素
erase(pos);// 删除pos迭代器所指的元素,返回下一个元素的迭代器
erase(beg, end);// 删除区间[beg, end)的所有元素
erase(elem);// 删除容器中值为elem的元素
    set<int> T;
    T.insert(5);
    T.insert(3);
    T.insert(4);
    T.insert(2);
    T.insert(9);

    Print_set(T);

    if(T.empty())
    {
        qDebug()<<"空";
    }
    else
    {
        qDebug()<<"大小:"<<T.size();
    }
    qDebug()<<"移除首位元素";
    T.erase(T.begin());
    Print_set(T);

    qDebug()<<"移除第3个元素";
    T.erase(3);
    Print_set(T);

find(key);// 查找键key是否存在,若存在,返回该元素的迭代器;若不存在,则返回map.end()
lower_bound(keyElem);// 返回第一个key>=keyElem元素的迭代器,若不存在,则返回map.end()
upper_bound(keyElem);// 返回第一个key>keyElem元素的迭代器,若不存在,则返回map.end()
equal_range(keyElem);// 返回容器中key和keyElem相等的上下限的两个迭代器,若不存在,则返回map.end(),此上下限就是lower_bound和upper_bound
    set<int>::iterator pos = T.find(3);

    if(pos!=T.end())
    {
        qDebug()<<"没有找到";
    }
    else
    {
        qDebug()<<"找到:值为"<<*pos;
    }
    

    pair<set<int>::iterator,set<int>::iterator> ret = T.equal_range(4);

    if(ret.first==T.end())
    {
        qDebug()<<"没有找到";
    }
    else
    {
        qDebug()<<"找到:值为"<<*(ret.first);
    }
    if(ret.second==T.end())
    {
        qDebug()<<"没有找到";
    }
    else
    {
        qDebug()<<"找到:值为"<<*(ret.second);
    }

注意:equal_range的接口,返回两个值,一个是lower_bound(keyElem),一个是upper_bound(keyElem)

此时使用pair进行接受返回值:

 关于对组(pair)

    pair<string,int>p(string("Tom"),100);
    cout<<"name:"<<p.first<<endl;
    cout<<"age:"<<p.second<<endl;

    pair<string,int>p2 = make_pair("jerry",10);
    cout<<"name:"<<p2.first<<endl;
    cout<<"age:"<<p2.second<<endl;

访问元素方式:第一个:frist;第二个:second;创建方式也同上

上述程序输出:

set不允许插入相同的值 

关于set,不允许插入重复的内容, 如果擦入会怎样?

    set<int> T;
    T.insert(9);
    T.insert(9);
    Print_set(T);

程序没有报错,打印之后输出了一个数值。

    set<int> T;

    pair<set<int>::iterator,bool> it1 = T.insert(9);
    if(it1.second == false)
    {
        qDebug()<<"插入失败";
    }
    else
    {
        qDebug()<<"插入成功";
    }
    pair<set<int>::iterator,bool> it2 = T.insert(9);
    if(it2.second == false)
    {
        qDebug()<<"插入失败";
    }
    else
    {
        qDebug()<<"插入成功";
    }
    Print_set(T);

查阅insert返回值可以看到,insert返回的是一个对组,对组第一个变量是迭代器,返回的是插入位置,第二个是bool变量,返回的是是否插入成功。

从输出也可以看出来,只要一次插入成功了。 

从大到小排序

set因为使用的是红黑树的结构,以此来在插入的时候就完成排序,此时要进行从大到小的排序

方法:在插入之前就规定好排序规则,使用仿函数

在插入前就要规定好原则,那么只能在set创建的时候了,set创建的过程中有一个重载,允许用户输入仿函数修改排序规则 

仿函数部分:

class MyCompare
{
public:
    bool operator()(int v1,int v2)
    {
        return v1>v2;
    }
};

使用方法:

    set<int,MyCompare> T;
    T.insert(5);
    T.insert(3);
    T.insert(4);
    T.insert(2);
    pair<set<int>::iterator,bool> it1 = T.insert(9);
    Print_set(T);

其中的输出API(要和set的建立一一对应)

void Print_set(set<int,MyCompare> T)
{
    qDebug()<<"遍历:";
    for(set<int,MyCompare>::iterator it = T.begin();it!=T.end();it++)
    {
        qDebug()<<*it;
    }
}

输出: 

 

插入自定义类型

其他的数据类型也可以如此

自定义类型:

class MyCompare
{
public:
    bool operator()(const PersonSet & p1,const PersonSet & p2)
    {
        if(p1.age>p2.age)
            return true;
        else
            return false;
    }
};

仿函数:

class MyCompare
{
public:
    bool operator()(const PersonSet & p1,const PersonSet & p2)
    {
        if(p1.age>p2.age)
            return true;
        else
            return false;
    }
};

打印接口:

void Print_set(set<PersonSet,MyCompare> T)
{
//    qDebug()<<"遍历:";
    for(set<PersonSet,MyCompare>::iterator it = T.begin();it!=T.end();it++)
    {
        cout<<"age:"<<(*it).age<<"name:"<<(*it).name<<endl;
    }
}

具体操作:

    set<PersonSet,MyCompare> T;
    PersonSet p1 = {string("1"),1};
    PersonSet p2 = {string("2"),2};
    PersonSet p3 = {string("3"),3};
    PersonSet p4 = {string("100"),100};
    PersonSet p5 = {string("123"),123};

    T.insert(p1);
    T.insert(p2);
    T.insert(p3);
    T.insert(p4);
    T.insert(p5);

    Print_set(T);

输出:

唯一要注意的是,打印接口,(*it)先访问存在迭代器中的值,也就是PersonSet类型的值,之后再进行访问其他成员的操作 

发布了85 篇原创文章 · 获赞 11 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_41605114/article/details/105032788
今日推荐