STL-常用容器

string容器

string构造函数

string本质:类

string和char*区别:

char* 是一个指针

string是一个类,类内部封装了char*,管理这个字符串,是一个char*型的容器。

特点:

string类内部封装了很多成员方法

如:查找find,拷贝copy,删除delete,替换replace,插入insert

string管理char*所分配的内存,不用担心赋值越界和取值越界等,由类内部进行负责

string(); //创建一个空的字符串,例如:string str;

string(const char* s); //使用字符串s初始化

string(const string& str); //使用一个string对象初始化另一个string对象

string(int n, char c); //使用n个字符c初始化

void test01()
{
    string s1;//创建空字符串,调用无参构造函数
    cout << s1 << endl;
    const char* str = "hellow";
    str = "ds";
    string s2(str);//把c_string转换成了string
    cout << s2 << endl;
    string s3(s2); //调用拷贝构造函数
    cout << s3 << endl;
    string s4(10, 'a');
    cout << s4 << endl;
}

string赋值操作

功能描述:

  • 给string字符串进行赋值

赋值的函数原型:

string& operator=(const char* s); //char*类型字符串 赋值给当前的字符串

string& operator=(const string& s); //把字符串s赋给当前的字符串

string& operator = (char c); //字符赋值给当前的字符串

string& assign(const char *s); //把字符串s赋给当前的字符串

string& assign(const char *s, int n); //把字符串s的前n个字符赋给当前的字符串

string& assign(const string &s); //把字符串s赋给当前字符串

string& assign(int n, char c); //用n个字符c赋给当前字符串

void test01()
{
    string s1;
    s1 = "hello world";
    cout << "s1: " << s1 << endl;
    string s2;
    s2 = s1;
    cout << "s2: " << s2 << endl;
    string s3;
    s3 = 'a';
    cout << "s3: " << s3 << endl;
    string s4;
    s4.assign("hewl");
    cout << "s4: " << s4 << endl;
    string s5;
    s5.assign(s4);
    cout << "s5: " << s5 << endl;
    string s6;
    s6.assign("hello world", 5);
    cout << "s6: " << s6 << endl;
    string s7;
    s7.assign(10, 'a');
    cout << "s7: " << s7 << endl;

 }

string字符串拼接

功能描述:

实现在字符串末尾拼接字符串

函数原型:

string& operator+=(const char* str); //重载+=操作符

string& operator+=(const char c); //重载+=操作符

string& operator+=(const string& str); //重载+=操作符

string& append(const char* s); //把字符串s链接到当前字符串结尾

string& append(const char* s, int n); //把字符串s的前n个字符链接到当前字符串结尾

string& append(const string &s); //同operator+=(const string& str)

string& append(conststring &s, int pos, int n);//字符串s中从pos开始的n个字符连接到字符串结尾

void test01()
{
    string str1 = "我";
    str1 += ':';
    cout << str1 << endl;
    str1 += "爱玩游戏";
    cout << str1 << endl;
    string str3 = "I";
    str3.append(" love ");
    cout << str3 << endl;
    string str4 = "lol dwl";
    str3.append(str4, 3);
    cout << str3 << endl;
    str3.append(" game ");
    cout << str3 << endl;
    //str3.append(str4, 0, 3);
    str3.append(str4, 4, 3);
    cout << str3 << endl;
}

string查找和替换

功能描述:

  • 查找:查找指定字符串是否存在
  • 替换:在指定的位置替换字符串

函数原型:

//查找
void test01()
{
    string str1 = "abcdefde";
    int pos = str1.find("de");   //3
    cout << pos << endl;
    pos = str1.rfind("de");      //6
    cout << pos << endl;
}
//替换
void test02()
{
    string str1 = "abcdefg";
    str1.replace(1, 3, "1111");
    cout << str1 << endl; //a1111efg
}

find和rfind区别:

find查找是从左往右,而rfind是从右往左

find找到字符串后返回查找的第一个字符位置,找不到则返回-1

replace在替换时,要指定从哪个位置起,多少个字符,替换成什么样的字符串

string字符串比较

功能描述:

  • 字符串之间比较

比较方式

  • 按字符的ASCII码进行对比

=返回 0

>返回 1

<返回 -1

函数原型:

int compare(const string& s) const; //与字符串比较

int compare(const char* s) const; //与字符串比较

void test01()
{
    string str1 = "hello";
    string str2 = "xello";
    if (str1.compare(str2) == 0)
    {
        cout << "两个字符串相等" << endl;
    }
    else if (str1.compare(str2) > 0)
    {
        cout << "str1 大于 str2" << endl;
    }
    else
    {
        cout << "str1 小于 str2" << endl;
    }
}

compare主要比较的是字符串是否相等,一般不比较大小

string字符存取

string中单个字符存取方式有两种

char& operator[](int n); //通过[]方式取字符

char& at(int n); //通过at方式取字符

void test01()
{
    string str1 = "hello world";
    for (int i = 0; i < str1.size(); ++i)
    {
        cout << str1[i] << " ";
    }
    cout << endl;
    for (int i = 0; i < str1.size(); ++i)
    {
        cout << str1.at(i) << " ";
    }
}

string插入和删除

功能描述:

对string字符串进行插入和删除字符操作

函数原型:

void test01()
{
    string str1 = "hello";
    //插入
    str1.insert(1, "111");
    cout << str1 << endl;
    //删除
    str1.erase(1, 3); //从第一个位置开始删除3个字符
    cout << str1 << endl;
}

插入和删除的下标都从0开始

string子串

功能描述:

  • 从字符串中获取想要的子串

函数原型:

string substr(int pos=0, int n=npos) const; //返回由pos开始的n个字符组成的字符串

void test01()
{
    string str1 = "abcdef";
    string str2 = str1.substr(1, 3); //bcd
    cout << str2 << endl;
}
void test02()
{
    string email = "lisi@163.com";
    //从邮件地址中 获取用户名信息
    //找到@位置
    int pos = email.find('@');
    string name = email.substr(0, pos);
    cout << name << endl;
}

vector容器

vector基本概念

功能:

  • vector数据结构与数组非常相似,也称为单端数组

vector与普通数组区别:

  • 不同之处在于数组是静态空间,而vector可以动态扩展

动态扩展:

  • 并不是在原空间之后续接新空间,而是找更大的内存空间,然后将原数据拷贝新空间,释放原空间。

vector容器的迭代器是支持随机访问的迭代器

vector构造函数

功能描述:

创建vector容器

函数原型:

void printVector(vector<int>& v)
{
    for (vector<int>::iterator it = v.begin(); it != v.end(); ++it)
    {
        cout << *it << " ";
    }
    cout << endl;
}
void test01()
{
    vector<int> v1; //默认构造,无参构造
    for (int i = 0; i < 10; ++i)
    {
        v1.push_back(i);
    }
    printVector(v1);
    //通过区间方式进行构造
    vector<int> v2(v1.begin(), v1.end());
    printVector(v2);
    //n个elem方式构造
    vector<int> v3(10, 100);
    printVector(v3);
    //拷贝构造
    vector<int> v4(v3);
    printVector(v4);
}

vector赋值操作

功能描述:

给vector容器进行赋值

函数原型:

void test01()
{
    vector<int> v1; //默认构造,无参构造
    for (int i = 0; i < 10; ++i)
    {
        v1.push_back(i);
    }
    printVector(v1);
    vector<int> v2 = v1;
    printVector(v2);
    //assign
    vector<int>v3;
    v3.assign(v2.begin(), v2.end());
    printVector(v3);
    vector<int>v4;
    v4.assign(10, 100);
    printVector(v4);
}

vector容量和大小

功能描述:

  • 对vector容器的容量和大小操作

函数原型:

void test01()
{
    vector<int> v1; //默认构造,无参构造
    for (int i = 0; i < 10; ++i)
    {
        v1.push_back(i);
    }
    printVector(v1);
    if (v1.empty())
    {
        cout << "v1为空!" << endl;
    }
    else
    {
        cout << "v1不为空!" << endl;
        cout << "v1的容量大小:" << v1.capacity() << endl;
        cout << "v1的大小:" << v1.size() << endl;
    }
    //重新指定大小
    //v1.resize(15);
    v1.resize(15, 10);
    printVector(v1);
    v1.resize(5);
    printVector(v1);
}

vector插入和删除

函数原型:

void test01()
{
    vector<int> v1; //默认构造,无参构造
    //尾插
    for (int i = 0; i < 5; ++i)
    {
        v1.push_back(i);
    }
    printVector(v1);
    //尾删
    v1.pop_back();
    printVector(v1);
    //插入
    v1.insert(v1.begin(), 10);
    printVector(v1);
    v1.insert(v1.begin(), 2, 20);
    printVector(v1);
    //删除,参数也是迭代器
    v1.erase(v1.begin());
    printVector(v1);

    //清空
    //v1.erase(v1.begin(), v1.end());
    v1.clear();
    printVector(v1);
}

vector数据存取

函数原型:

void test01()
{
    vector<int> v1; //默认构造,无参构造
    for (int i = 0; i < 10; ++i)
    {
        v1.push_back(i);
    }
    for (int i = 0; i < v1.size(); ++i)
    {
        cout << v1[i] << " ";
    }
    cout << endl;
    for (int i = 0; i < v1.size(); ++i)
    {
        cout << v1.at(i) << " ";
    }
    cout << endl;
    cout << v1.front() << endl;
    cout << v1.back() << endl; 
}

vector互换容器

功能描述:

实现两个容器内元素进行互换

函数原型:

swap(vec); //将vec于本身的元素互换

void test01()
{
    vector<int> v1; //默认构造,无参构造
    for (int i = 0; i < 100000; ++i)
    {
        v1.push_back(i);
    }
    cout << "v1的容量大小:" << v1.capacity() << endl;
    cout << "v1的大小:" << v1.size() << endl;
    v1.resize(3); //重新指定大小
    cout << "v1的容量大小:" << v1.capacity() << endl;
    cout << "v1的大小:" << v1.size() << endl;
    //巧用swap收缩内存
    vector<int>(v1).swap(v1);
    cout << "v1的容量大小:" << v1.capacity() << endl;
    cout << "v1的大小:" << v1.size() << endl;
}

此匿名对象按照v进行初始化,故此匿名对象会按照v目前所用的个数作为初始化,即初始的容量是v的size大小

vector预留空间

功能描述:

减少vector在动态扩展容量时的扩展次数

函数原型:

reverse(int len); //容器预留len个元素,预留位置不初始化,元素不可访问

void test01()
{
    vector<int> v1; //默认构造,无参构造
    //预留空间
    v1.reserve(100000);
    int num = 0;
    int* p = NULL;
    for (int i = 0; i < 100000; ++i)
    {
        v1.push_back(i);
        if (p != &v1[0])
        {
            p = &v1[0];
            num++;
        }
    }
    cout << num << endl; //不预留空间时,num=30
    //预留空间时,num=1
}

如果数据量较大,可以一开始利用reserve预留空间

deque容器

deque容器基本概念

功能:

双端数组,可以对头端进行插入删除操作

deque与vector区别:

  • vector对于头部的插入删除效率低,数据量越大,效率越低
  • deque相对而言,对头部的插入删除速度会比vector快
  • vector访问元素时的速度会比deque快,这和两者内部实现有关

deque内部工作原理:

deque内部有个中控器,维护每段缓冲区中的内容,缓冲区中存放真实数据

中控器维护的是每个缓冲区的地址,使得使用deque时像一篇连续的内存空间

deque容器的迭代器也是支持随机访问的

deque构造函数

函数原型:

//const打印,防止数据修改
void printDeque(const deque<int>& v)
{
    for (deque<int>::const_iterator it = v.begin(); it != v.end(); ++it)
    {
        cout << *it << " ";
    }
    cout << endl;
}

void test01()
{
    deque<int> d1;
    for (int i = 0; i < 10; ++i)
    {
        d1.push_back(i);
    }
    printDeque(d1);
    deque<int> d2(d1.begin(), d1.end());
    printDeque(d2);
    deque<int> d3(d2);
    printDeque(d3);
    deque<int> d4(10, 2);
    printDeque(d4);

}

赋值操作

void test01()
{
    deque<int> d1;
    for (int i = 0; i < 10; ++i)
    {
        d1.push_back(i);
    }
    printDeque(d1);
    deque<int> d2 = d1;
    printDeque(d2);
    deque<int> d3;
    d3.assign(d2.begin(), d2.end());
    printDeque(d3);
    deque<int> d4;
    d4.assign(10, 2);
    printDeque(d4);
}

deque大小操作

deque插入和删除

函数原型:

void test01()
{
    deque<int> d1;
    for (int i = 0; i < 10; ++i)
    {
        d1.push_back(i);
    }
    printDeque(d1);
    d1.push_front(11);
    printDeque(d1);
    d1.pop_back();
    d1.pop_back();
    printDeque(d1);
    d1.pop_front();
    d1.pop_front();
    printDeque(d1);
    d1.insert(d1.begin() + 2, 100);
    printDeque(d1);
    //删除
    deque<int>::iterator it = d1.begin();
    it++;
    d1.erase(it);
    printDeque(d1);
    //区间删除
    //d1.erase(d1.begin(), d1.end());
    //清空
    d1.clear();
    printDeque(d1);
}

deque数据存取

函数原型:

deque排序

算法:

sort(iterator beg, iterator end); //对beg和end区间内元素进行排序

void test01()
{
    deque<int> d1;
    for (int i = 0; i < 10; ++i)
    {
        d1.push_back(i);
    }
    printDeque(d1);
    d1.push_front(11);
    d1.push_front(12);
    d1.push_front(13);
    printDeque(d1); //13 12 11 0 1 2 3 4 5 6 7 8 9
    //排序,默认排序规则:从小到大,升序
    //对于支持随机访问的迭代器的容器,都可以利用sort算法直接排序
    //vector容器也可以利用sort排序
    sort(d1.begin(), d1.end());
    cout << "排序后:" << endl;
    printDeque(d1);
}

案例:评委打分

void printPerson(vector<Person>& v)
{
    for (vector<Person>::iterator it = v.begin(); it != v.end(); ++it)
    {
        cout << "姓名:" << (*it).m_Name << ",平均分:" << (*it).m_Score << endl;
    }
}
void createPerson(vector<Person>& v)
{
    string nameSeed = "ABCDE";
    for (int i = 0; i < 5; ++i)
    {
        string name = "选手";
        name += nameSeed[i];
        int score = 0;
        Person p(name, score);
        v.push_back(p);
    }
}
void setScore(vector<Person>& v)
{
    
    for (vector<Person>::iterator it = v.begin(); it != v.end(); ++it)
    {
        deque<int>d;
        for (int i = 0; i < 10; ++i)
        {
            int score = rand() % 41 + 60;
            d.push_back(score);

        }
        //排序
        sort(d.begin(), d.end());
        //去掉最高和最低分
        d.pop_back();
        d.pop_front();
        //printDeque(d);
        //取平均分
        int sum = 0;
        for (deque<int>::iterator dit = d.begin(); dit != d.end();++dit)
        {
            sum += *dit;
        }
        int avg = sum / d.size();
        (*it).m_Score = avg;
    }
}
void test01()
{
    //随机种子
    srand((unsigned int)time(NULL));
    //初始化五名选手
    vector<Person> v;
    createPerson(v);
    //printPerson(v);
    //打分数
    setScore(v);
    printPerson(v);
}

stack容器

stack基本概念

stack是一种先进后出(First In Last Out)的数据结构,它只有一个出口

栈中只有顶端元素才可被外界使用,因为栈不允许有遍历行为

stack常用接口

void test01()
{
    stack<int> s;
    //入栈
    s.push(10);
    s.push(20);
    s.push(30);
    s.push(40);
    cout << "栈的大小:" << s.size() << endl;
    while (!s.empty())
    {
        cout << "栈顶元素:" << s.top() << endl;
        //出栈
        s.pop();
    }
    cout << "栈的大小:" << s.size() << endl;

}
  • 入栈:push
  • 出栈:pop
  • 返回栈顶:top
  • 判断栈是否为空:empty
  • 返回栈大小:size

queue容器

queue基本概念

先进先出

队列容器允许从一端新增元素,从另一端移除元素

只有队头和队尾可用,不允许有遍历行为

进数据称为 -- 入队 push

出数据称为 -- 入队 pop

queue常用接口

list容器

list基本概念

功能:将数据进行链式存储

链表(list)是一种物理存储单元上非连续的存储结构,数据元素的逻辑顺序是通过链表中的指针链接实现的。

链表组成:由一系列结点组成

结点组成:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域

STL中链表是一个双向循环链表

由于链表的存储方式并不是连续的内存空间,因此链表list中的迭代器只能前移和后移,属于双向迭代器

list的优点:

  • 采用动态存储分配,不会造成内存浪费和溢出
  • 链表执行插入和删除操作十分方便,修改指针即可,不需要移动大量元素

list的缺点:

链表灵活,但空间(指针域)和时间(遍历)额外耗费较大

list的插入和删除操作都不会造成原有list迭代器的失效,这在vector中是不成立的。

总结:STL中list和vector是两个最常被使用的容器,各有优缺点

list构造函数

函数原型:

void printList(const list<int>& l)
{
    for (list<int>::const_iterator it = l.begin(); it != l.end(); ++it)
    {
        cout << *it << " ";
    }
    cout << endl;
}
void test01()
{
    list<int> l1;//默认构造
    l1.push_back(10);
    l1.push_back(20);
    l1.push_back(30);
    l1.push_back(40);
    printList(l1);
    list<int>l2(l1.begin(), l1.end());
    printList(l2);
    list<int>l3(l2);
    printList(l3);
    list<int>l4(10, 2);
    printList(l4);
}

list赋值和交换

void test01()
{
    list<int> l1;//默认构造
    l1.push_back(10);
    l1.push_back(20);
    l1.push_back(30);
    l1.push_back(40);
    printList(l1);
    list<int>l2 = l1;
    printList(l2);
    list<int>l3;
    l3.assign(l2.begin(), l2.end());
    printList(l3);
    list<int>l4;
    l4.assign(10, 12);
    printList(l4);
}
void test02()
{
    list<int> l1;//默认构造
    l1.push_back(10);
    l1.push_back(20);
    l1.push_back(30);
    l1.push_back(40);
    list<int>l4;
    l4.assign(10, 12);
    printList(l1);
    printList(l4);

    l1.swap(l4);
    cout << "交换后:" << endl;
    printList(l1);
    printList(l4);
}

list大小操作

函数原型:

list插入和删除

函数原型:

void test01()
{
    list<int> l1;//默认构造
    //尾插
    l1.push_back(10);
    l1.push_back(20);
    l1.push_back(30);
    l1.push_back(40);
    printList(l1);
    //头插
    l1.push_front(10);
    l1.push_front(20);
    printList(l1);
    //尾删
    l1.pop_back();
    printList(l1);
    //头删
    l1.pop_front();
    printList(l1);
    
    l1.insert(l1.begin(), 3, 2);
    printList(l1);
    l1.insert(l1.begin(), 1);
    printList(l1);
    l1.erase(++l1.begin());
    //l1.clear();
    printList(l1);
    l1.remove(2);
    printList(l1);
}

尾插:push_back

尾删:pop_back

头插:push_front

头删:pop_front

插入:insert

删除:erase

移除:remove

清空:clear

list数据存取

函数原型:

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

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

迭代器只能用it++或it--,不能it=it+1等,即不能随机访问

list反转和排序

函数原型:

reverse; //反转链表

sort(); //链表排序

所有不支持随机访问迭代器的容器,不可以用标准算法

不支持随机访问的迭代器的容器,内部会提供对应一些算法

bool myCompare(int v1, int v2)
{
    return v1 > v2;
}
void test01()
{
    list<int> l1;//默认构造
    //尾插
    l1.push_back(10);
    l1.push_back(20);
    l1.push_back(30);
    l1.push_back(40);
    printList(l1);
    //头插
    l1.push_front(80);
    l1.push_front(70);
    printList(l1);
    //反转
    l1.reverse();
    printList(l1);
    //所有不支持随机访问迭代器的容器,不可以用标准算法
    // 不支持随机访问的迭代器的容器,内部会提供对应一些算法
    //sort(l1.begin(), l1.end());
    
    //排序
    l1.sort();//默认从小到大,升序
    printList(l1);
    l1.sort(myCompare);//降序
    printList(l1);
}

排序案例

class Person
{
public:
    Person(string name, int age, int height)
    {
        m_Name = name;
        m_Age = age;
        m_Height = height;
    }
    string m_Name;
    int m_Age;
    int m_Height;
};
void printLP(list<Person>& l)
{
    for (list<Person>::iterator it = l.begin(); it != l.end(); ++it)
    {
        cout << "姓名:" << (*it).m_Name << ",年龄:" << (*it).m_Age << ",身高:" << (*it).m_Height << endl;
    }
}
bool comPerson(Person p1, Person p2)
{
    if (p1.m_Age == p2.m_Age)
    {
        return p1.m_Height > p2.m_Height;
    }
    return p1.m_Age < p2.m_Age;
}
void test01()
{
    list<Person>l;
    Person p1("刘备", 35, 175);
    Person p2("曹操", 45, 180);
    Person p3("孙权", 40, 170);
    Person p4("赵云", 25, 190);
    Person p5("张飞", 35, 160);
    Person p6("关羽", 35, 200);
    l.push_back(p1);
    l.push_back(p2);
    l.push_back(p3);
    l.push_back(p4);
    l.push_back(p5);
    l.push_back(p6);
    printLP(l);
    l.sort(comPerson);
    cout << "排序后=============" << endl;
    printLP(l);

}

set/multiset容器

set基本概念

所有元素都会在插入时自动被排序

本质:set/multiset属于关联式容器,底层结构是用二叉树实现

set和multiset区别:

set不允许容器有重复元素

multiset允许容器有重复元素

set构造和赋值

void printSet(const set<int>& s)
{
    for (set<int>::const_iterator it = s.begin(); it != s.end(); ++it)
    {
        cout << *it << " ";
    }
    cout << endl;
}
void test01()
{
    set<int>s;
    //set插入只有insert,没有其他函数
    s.insert(10);
    s.insert(30);
    s.insert(40);
    s.insert(20);
    s.insert(30);
    printSet(s);
    set<int>s2 = s;
    printSet(s2);
    set<int>s3(s2);
    printSet(s3);
}

set大小和交换

不能重新定义容器大小,没有resize函数

set插入和删除

函数原型:

void test01()
{
    set<int>s;
    //set插入只有insert,没有其他函数
    s.insert(10);
    s.insert(30);
    s.insert(40);
    s.insert(20);
    s.insert(30);
    printSet(s);
    //删除
    s.erase(s.begin());
    printSet(s);
    s.erase(40);
    printSet(s);
    /*s.erase(s.begin(), s.end());
    printSet(s);*/
    s.clear();
    printSet(s);
}

set查找和统计

函数原型:

void test01()
{
    set<int>s;
    //set插入只有insert,没有其他函数
    s.insert(10);
    s.insert(30);
    s.insert(40);
    s.insert(20);
    s.insert(30);
    printSet(s);
    set<int>::iterator pos = s.find(30);
    if (pos != s.end())
    {
        cout << "找到了元素" << *pos << endl;
    }
    else
    {
        cout << "没找到" << endl;
    }
    //统计
    int sum = s.count(100);
    cout << sum << endl;
}

pair对组创建

成对出现的数据,利用对组可以返回两个数据

两种创建方式:

void test01()
{
    //第一种方式
    pair<string, int> p("tom", 18);
    cout << "姓名:" << p.first << ",年龄:" << p.second << endl;
    //第二种方式
    pair<string, int>p2 = make_pair("jerry", 20);
    cout << "姓名:" << p2.first << ",年龄:" << p2.second << endl;
}

set容器排序

set容器默认排序规则为从小到大,利用仿函数,可以改变排序规则

class CompareSet
{
public:
    bool operator()(int v1, int v2)const
    {
        return v1 > v2;
    }
};
void test01()
{
    set<int>s;
    //set插入只有insert,没有其他函数
    s.insert(10);
    s.insert(30);
    s.insert(40);
    s.insert(20);
    s.insert(30);
    printSet(s);
    //在插入数据之后没有办法改变排序规则
    set<int, CompareSet> s2;
    s2.insert(10);
    s2.insert(30);
    s2.insert(40);
    s2.insert(20);
    s2.insert(30);
    for (set<int, CompareSet>::iterator it = s2.begin(); it != s2.end(); ++it)
    {
        cout << *it << " ";
    }
    cout << endl;
}

set存放自定义数据类型,排序方式要自己定义

class Person
{
public:
    Person(string name, int age)
    {
        m_Name = name;
        m_Age = age;
    }
    string m_Name;
    int m_Age;
};
class ComPerson
{
public:
    bool operator()(Person p1, Person p2) const
    {
        return p1.m_Age < p2.m_Age;
    }
};

void test01()
{
    //自定义数据类型,都会指定排序规则
    set<Person, ComPerson>s;
    Person p1("tony", 18);
    Person p2("lily", 28);
    Person p3("son", 16);
    s.insert(p1);
    s.insert(p2);
    s.insert(p3);
    for (set<Person>::iterator it = s.begin(); it != s.end(); ++it)
    {
        cout << "姓名:" << (*it).m_Name << ",年龄:" << (*it).m_Age << endl;
    }
    
}

map/multimap容器

map基本概念

map中所有元素都是pair

pair中第一个元素为key(键值),起到索引作用,第二个元素为value(实值)

所有元素都会根据元素的键值自动排序

本质:

map/multimap属于关联式容器,底层结构用二叉树实现。

优点:

可根据key值快速找到value值

map和multimap区别:

map不允许容器中有重复key值元素

multimap允许容器中有重复key值元素

map构造和赋值

函数原型:

void printMap(const map<int, int>&m)
{
    for (map<int, int>::const_iterator it = m.begin(); it != m.end(); ++it)
    {
        cout << "key: " << (*it).first << ", value: " << (*it).second << endl;
    }
}
void test01()
{
    map<int, int>m;
    m.insert(pair<int, int>(1, 10));
    m.insert(pair<int, int>(2, 20));
    m.insert(pair<int, int>(3, 40));
    printMap(m);
    cout << "=======================" << endl;
    map<int, int>m2(m);
    printMap(m2);
    cout << "=======================" << endl;
    map<int, int>m3 = m2;
    printMap(m3);
}

map大小和交换

函数原型:

map插入和删除

函数原型:

void test01()
{
    map<int, int>m;
    //插入方式1
    m.insert(pair<int, int>(1, 10));
    //插入方式2
    m.insert(make_pair(2, 20));
    //插入方式3
    m.insert(map<int, int>::value_type(3, 30));
    //插入方式4
    m[4] = 40;
    printMap(m);
    cout << "=======================" << endl;
    m.erase(m.begin());
    printMap(m);
    cout << "=======================" << endl;
    m.erase(3);
    printMap(m);
    //m.erase(m.begin(), m.end());
    m.clear();
    printMap(m);
    
}

map查找和统计

函数原型:

map容器排序

利用仿函数,可以改变排序规则

STL案例 - 员工分组

案例描述:

实现步骤:

class Worker
{
public:
    string m_Name;
    int m_Salary;
};
void createWorker(vector<Worker>& v)
{
    string nameSeed = "ABCDEFGHIJ";
    for (int i = 0; i < 10; ++i)
    {
        Worker w;
        w.m_Name = "员工";
        w.m_Name += nameSeed[i];
        w.m_Salary = rand()%10000+10000;
        v.push_back(w);   
    }
}
void printWorker(vector<Worker>& w)
{
    for (vector<Worker>::iterator it = w.begin(); it != w.end(); ++ it)
    {
        cout << "姓名:" << (*it).m_Name << ",工资:" << it->m_Salary << endl;
    }
}
void setDepartment(multimap<int, Worker>& d, vector<Worker> worker)
{
    for (vector<Worker>::iterator it=worker.begin(); it!=worker.end(); ++it)
    {
        int k = rand() % 3;
        d.insert(make_pair(k, *it));
    }
}
void showWorkerByGroup(multimap<int, Worker>& m)
{
    cout << "策划部门:" << endl;
    multimap<int, Worker>::iterator it = m.find(CEHUA);
    int count = m.count(CEHUA);
    int index = 0;
    /*while (it != m.end() && (*it).first == CEHUA)
    {
        cout << "姓名:" << (*it).second.m_Name << ",工资:" << it->second.m_Salary << endl;
        it++;
    }
    cout << "美术部门:" << endl;
    it = m.find(MEISHU);
    while (it != m.end() && (*it).first == MEISHU)
    {
        cout << "姓名:" << (*it).second.m_Name << ",工资:" << it->second.m_Salary << endl;
        it++;
    }
    cout << "研发部门:" << endl;
    it = m.find(YANFA);
    while (it != m.end() && (*it).first == YANFA )
    {
        cout << "姓名:" << (*it).second.m_Name << ",工资:" << it->second.m_Salary << endl;
        it++;
    }*/
    while (it != m.end() && index < count)
    {
        cout << "姓名:" << (*it).second.m_Name << ",工资:" << it->second.m_Salary << endl;
        it++;
        index++;
    }
    cout << "美术部门:" << endl;
    it = m.find(MEISHU);
    count = m.count(MEISHU);
    index = 0;
    while (it != m.end() && index < count)
    {
        cout << "姓名:" << (*it).second.m_Name << ",工资:" << it->second.m_Salary << endl;
        it++;
        index++;
    }
    cout << "研发部门:" << endl;
    it = m.find(YANFA);
    count = m.count(YANFA);
    index = 0;
    while (it != m.end() && index < count)
    {
        cout << "姓名:" << (*it).second.m_Name << ",工资:" << it->second.m_Salary << endl;
        it++;
        index++;
    }
}
void test01()
{
    //创建员工
    vector<Worker> worker;
    createWorker(worker);
    printWorker(worker);
    //对员工分部门
    multimap<int, Worker>depeartment;
    setDepartment(depeartment, worker);
    showWorkerByGroup(depeartment);
}
int main()
{
    srand((unsigned int)time(NULL));
    system("pause");
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值