C++语言之STL

STL

STL是标准模板库,是惠普实验室开发的一系列软件的统称

STL的6大组件

        容器 算法 迭代器 仿函数 适配器 空间适配器

容器

作用:容纳存储的数据

分类:

        序列式容器:

                强调值的顺序,每个元素均有固定的位置,除非用删除或插入的操作改变这个位置,如vector,deque/queue,list;

        关联式容器:

                非线性,为二叉树结构,各元素之间没有严格的物理上的顺序关系

                在数据中选择一个关键字key,这个key对数据起到索引的作用,方便查找

                如: set/multiset, map/multimap 容器

注意:

        容器可以嵌套容器

算法

作用:操作数据,如插入数据,删除数据,修改数据,排序等

分类:

        质变算法:是指运算过程中可以改变区间内的元素内容,如拷贝,替换,删除等

        非质变算法:是指运算过程中不会更改区间内的元素内容,例如查找,计数,遍历,寻找极值等

迭代器

作用:容器与算法之间的粘合剂

注意:每个容器都有自己的迭代器

分类:

        输入迭代器,提供对数据的只读访问,只读,支持++ == ! =

        输出迭代器,提供对数据的只写访问,只写,支持++

        前向迭代器,提供读写操作,并能向前推进迭代器,读写,支持++ == ! =

        双向迭代器,提供读写操作,并能向前向后操作,读写,支持++ --

        随机访问迭代器,提供读写操作,并能以跳跃的方式访问容器的任意数据,是功能最强的迭代器读写,支持++ -- [n] - n < <= > >=    

仿函数

作用:为算法提供策略

适配器

作用:为算法提供更多的参数接口

空间适配器

为容器和算法管理空间

常用容器

string

作用:存储字符的容器(字符串)

构造函数:

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

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

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

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

void fun01()

{

        string str01;

        cout<<"str01"<<endl;

        string str02("hello");

        cout<<"str02"<<endl;

        string str03 = str02;

        cout<<"str03"<<endl;

        string str04(3,'a');

        cout<<"str04"<<endl;

}

基本赋值操作

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个字符赋值给当前的字符串

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

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

string& assign(const string &s,int start,int n);//将s从start开始的n个字符赋值给字符串

获取字符串长度

语法:

        字符串.size()

        字符串.length();

注意:

        不包含\0

void fun()

{

        string str = "hello";

        int size = str.size();

        cout<<size<<endl;

        int len = str.length();

        cout<<len<<endl;

}

存取字符操作

语法:

        char& operator[](int n);//通过[]方式取字符串,下标越界不会抛出异常

        char& at(int n);//通过at方法获取字符,下标越界会抛出异常        

void fun()

{

        string str = "hello";

        cout<<str[2]<<endl;

        cout<<str.at(1)<<endl;

}

拼接操作

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

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

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

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

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

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

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

string& append(int n,char c);//在当前字符串结尾添加n个字符

void fun()

{

        string str01 = "hi";

        str01+="C++";

        cout<<"str01"<<endl;

        string srt02 = "STL";

        str01+=str02;

        cout<<str01<<endl;

        str+='A';

        cout<<str01<<endl;

}

void fun()

{

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

string str01;

str01.append("hi");

cout<<str01<<endl;

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

string str02;

str02.append("asdffghj",6);

cout<<str02<<endl;

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

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

string str03 = "1234567890";

string str04;

str04.append(str03,3,2);

cout<<str04<<endl;

//string& append(int n,char c);//在当前字符串结尾添加n个字符c

str04.append(2,'w');

cout<<str04<<endl;

}

查找和替换

ps:

        当在类的成员函数后面加上const关键字时,它表示这个成员函数是一个 “常量成员函数”。这意味着该函数不会修改它所属对象的状态(即不会修改对象的数据成员)。

int find(const string& str,int pos = 0)const;//查找str第一次出现的位置,从pos开始查找

intfind(const char *s,int pos = 0)const;//查找s第一次出现的位置,从pos开始查找

int find(const char*s,int pos,int n)const;//从pos位置开始,查找字符串s中前n个字符里特定字符(假设这里查找的是字符ch,可根据实际情况调整)第一次出现的位置 

int find(const char c,int pos = 0)const;//查找字符c第一次出现的位置

int rfind(const string& str,int pos = npos)const;//查找str最后一次出现的位置,从pos开始查找

int rfind(const char* s,int pos= npos)const;//查找s最后一次出现的位置,从pos开始查找

int rfind(const char*s, int pos,int n)const;//从pos位置开始,查找字符串s中前n个字符里特定字符(假设这里查找的是字符ch,可根据实际情况调整)最后一次出现的位置 

string& replace(int pos,int n,const string&str);//替换从pos开始的n个字符为字符串str

string& replace(int pos,int n,const char* s);//替换从pos开始n个字符为字符串s


注意:查找不存在返回-1

void fun()

{

        string str = "12345654321";

        int a1 = str.find('2');

        cout<<a1<<endl;

        int a2 = str.find("56");

        cout<<a2<<endl;

        int a3 = str.rfind('2');

        cout<<a3<<endl;

        str.replace(3,3,"7890");

        cout<<str<<endl;

}

比较操作

/*

        compare函数在大于时返回1,小于时返回-1,等于时返回0

        比较区分大小写,按照字典顺序,排在越前面越小,A比a小

*/

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

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

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

class MyString {
private:
    string data;
public:
    MyString(const string& str) : data(str) {}

    // 比较当前对象与传入的std::string类型字符串
    int compare(const string& s) const {
        return this->data.compare(s);
    }

    // 比较当前对象与传入的C风格字符串(以'\0'结尾的字符数组)
    int compare(const char* s) const {
        return this->data.compare(s);
    }
};

int main() {
    MyString myStr("hello");
    string otherStr = "world";
    const char* cStr = "hello";

    // 调用compare函数比较MyString对象和std::string对象
    int result1 = myStr.compare(otherStr);
    if (result1 < 0) {
        cout << "myStr 小于 otherStr" << endl;
    } else if (result1 > 0) {
        cout << "myStr 大于 otherStr" << endl;
    } else {
        cout << "myStr 等于 otherStr" << endl;
    }

    // 调用compare函数比较MyString对象和C风格字符串
    int result2 = myStr.compare(cStr);
    if (result2 < 0) {
        cout << "myStr 小于 cStr" << endl;
    } else if (result2 > 0) {
        cout << "myStr 大于 cStr" << endl;
    } else {
        cout << "myStr 等于 cStr" << endl;
    }

    return 0;
}

截取操作

语法:

        string substr(int pos = 0,int n= npos)const;

        //返回由pos开始的n个字符组成的字符串

void fun()

{

        string str01="a.txt";

        string str02 = str01.substr(1,4);

        cout<<str02<<endl;

}

插入与删除

语法:

        string& insert(int pos,const char* s);//指定位置插入字符串

        string& insert(int pos,const string& str);//指定位置插入字符串

        string& insert(int pos,int n,char c);//在指定位置插入n个字符c

        string& erase(int pos,int n = npos);//删除从pos开始的n个字符

void fun()

{

        string str01 = "11";

        str01.insert(1,3,'A');

        cout<<str01<<endl;

        str01.erase(1,3);//删除从pos开始的n个字符

        cout<<str01<<endl;

}

string与char*转换

语法:

 stringchar*

        最常用的是c_str()函数,它返回一个const char*指针,指向string对象内部以'\0'结尾的字符数组,但内容是常量。例如:const char* cstr = str.c_str();

   data()函数也能返回字符数组指针,和c_str()类似,但对结尾'\0'的保证稍弱。如const char* cstr = str.data();

        若要修改内容,可以把string内容复制到新的char数组,如通过strcpy函数:char char_array[100]; std::strcpy(char_array, str.c_str());
 

char*string

        简单的方式是直接初始化或赋值。例如:char* cstr = "Hello"; std::string str1(cstr);或者std::string str2; str2 = cstr;

        也可以利用string的构造函数进行转换,还能指定字符范围等,如std::string str(cstr, 0, 5);

vector

连续开辟,单向开口,随机访问迭代器,有容量,每次扩容是原来的两倍

底层数据结构:数组


与数组的区别:

        vector的结构类同于数组,数组是静态的,大小是在定义时确定的

        而vector是动态的,添加元素时如果空间不足时,则会自动扩容(2^n);这被称为vector的未雨绸缪机制

        整体来说,vector比较灵活,而且vector是类模版,可以存放任意类型的元素

迭代器

构造函数

语法:

        vector<T> v;//采用模版类实现,默认构造函数

        vector(v.begin(),v.end());//将v[begin(),end()]区间中的元素拷贝给本身

        vector(n,elem);//构造函数将n个elem拷贝给本身

        vector(const vector &vec);//拷贝构造函数

void fun01()

{

        vector<int> v01;

        v01.push_back(1);//尾部添加

        v01.push_back(5);

        v01.push_back(3);

        vector<int>::iterator it = v01.begin();//获取开始位置的迭代器

        while(it != v01.end())        //end():结束的位置

        {

                cout<< *it <,endl;         //*it获取当前迭代器指向的位置的值

                it++;//迭代器后移1位

        }

}

void fun02()

{

        vector<int> v01;

        v01.push_back(1);//尾部添加

        v01.push_back(5);

        v01.push_back(3);

        
        vector<int> v02(v01.begin()+1,v01.begin()+2);//包含开始位置,不包含结束位置(前闭后开)

        auto it = v02.begin();//C++11及以上版本,编译时需加-std = c+=11

        while(it != v02.end())

        {

                cout<<*it<<endl;

                it++;

        }

}

        void fun03()

        {

                vector<int> v(10,5);

                auto it = v.begin();

                while(it !=v.end())

                {

                        cout<<*it<<endl;

                        it++;

                }

        }

赋值操作

assign(beg,end);        //将[beg,end)区间中的数据拷贝赋值给本身

assign(n,elem);        将n个elem拷贝赋值给本身

vector& operator=(const vector &vec);        // 重载等号操作符

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

void fun04()

{

        vector<int> v01;

        v01.push_back(1);

        v01.push_back(5);

        v01.push_back(3);

        v01.push_back(9);

        v01.push_back(7);

        vector<int> v02;

        v02.push_back(2);

        v02.push_back(4);

        v02.swap(v01);

        auto it = v02.begin();

        while(it != v02.end())

        {

                cout<<*it<<endl;

                it++;

        }

        auto it01 = v01.begin();

        while(it01 != v01.end())

        {

                cout<<*it01<<endl;

                it01++;

        }

}

插入与删除

push_back(ele);        //尾部插入元素ele

insert(const_iterator pos,int cout,T ele);        //迭代器指向位置pos插入count个元素ele

pop_back();        //删除最后一个元素

erase(const_iterator start,const_iterator end);        //删除迭代器从start到end之间的元素,删除[start,end)区间的所有元素

erase(const_iterator pos);//删除迭代器指向的元素

clear();        //删除容器中所有元素

void fun05()
{
        vector<int> v;
        // push_back(ele); //尾部插入元素 ele
        v.push_back(1);
        v.push_back(3);
        v.push_back(5);
        v.push_back(7);
        // insert(const_iterator pos, int count, T ele); //迭代器指向位置pos 插入 count 个元素 ele.
        v.insert(v.begin(),1,0);
        // pop_back();//删除最后一个元素
        v.pop_back();
        //v.pop_back();
        // erase(const_iterator start, const_iterator end); //删除迭代器从start 到 end 之间的元素 , 删除 [start, end) 区间的所有元素
        v.erase(v.begin()+1,v.begin()+3);
        // erase(const_iterator pos); //删除迭代器指向的元素
        v.erase(v.begin());
        // clear(); //删除容器中所有元素
        v.clear();
        auto it = v.begin();
        while(it != v.end())
        {
                cout << *it << endl;
                it++;
        }
}

 取值操作

at(int idx);        //返回索引idx所指的数据,如果idx越界,抛出out_of_range异常

operator[](int idx);        //        返回索引idx所指的数据,越界时,不会直接报错

front();        //返回容器中第一个数据元素

back();        //返回容器中最后一个数据元素

void fun06()

{

        vector<int> v;

        v.push_back(1);
        v.push_back(3);
        v.push_back(5);
        v.push_back(7);
        // at(int idx); //返回索引 idx 所指的数据,如果 idx 越界,抛出
        out_of_range 异常。
        cout << "v.at(3) = " << v.at(3) << endl;
        // operator[](int idx); //返回索引 idx 所指的数据,越界时,不会报错
        cout << "v[2] = " << v[100] << endl;
        // front(); //返回容器中第一个数据元素
        cout << v.front() << endl;
        // back(); //返回容器中最后一个数据元素
        cout << v.back() << endl;

}

大小相关

int size(); //返回容器中元素的个数

bool empty(); //判断容器是否为空,返回bool值(0,1)

void resize(int num);        //重新指定的长度为num,若容器变长,则以默认值填充新位置,如果容器变短,则末尾超出容器的长度被删除

int capacity();        //容器的容量

void reserve(int len);        //容器预留len个元素长度

void fun07()
{
        vector<int> v;
        v.push_back(1);
        v.push_back(3);
        v.push_back(5);
        v.push_back(7);
        v.push_back(9);
        // int size(); // 返回容器中元素的个数
        // cout << v.size() << endl;
        // bool empty(); //判断容器是否为空, 返回 bool 值( 0 1
        // cout << v.empty() << endl;
        // void resize(int num); //重新指定容器的长度为 num ,若容器变长,则以默认值填充新位置。如果容器变短,则末尾超出容器长度的元素被删除。
        // v.resize(2);
        // void resize(int num, elem); //重新指定容器的长度为 num ,若容器变长,则以 elem 值填充新位置。如果容器变短,则末尾超出容器长度的元素被删除。
        // v.resize(10,10);
       // int capacity(); //容器的容量
        cout << v.capacity() << endl;
        // void reserve(int len); //容器预留 len 个元素长度
        v.reserve(10);
        cout << v.capacity() << endl;
        // auto it = v.begin();
        // while(it != v.end())
        // {
                // cout << *it << endl;
                // it++;
         // }
        }
void fun08()
{
        vector<int> v;
        v.push_back(1);
        v.push_back(3);
        v.push_back(5);
        v.push_back(7);
        v.push_back(9);
        cout << "v的大小 = " << v.size() << endl;
        cout << "v的容量 = " << v.capacity() << endl;
        vector<int>(v).swap(v);
        cout << "v的大小 = " << v.size() << endl;
        cout << "v的容量 = " << v.capacity() << endl;
}

 存储自定义类型

class Per

{

        public:

        Per(char *name)

        {

                this->name = name;

        }

};

void fun09()

{

        vector <Per> ps;

        ps.push_back(Per("张三"));

        ps.push_back(Per("李四"));

        ps.push_back(Per("王五"));

        for(auto it = ps.begin(); it != ps.end(); it++)

        {

                cout<<(*it).name<<endl;

        }

}

容器嵌套

void fun10()
{
vector<int> v1;
v1.push_back(10);
v1.push_back(20);
v1.push_back(30);
v1.push_back(40);
v1.push_back(50);
vector<int> v2;
v2.push_back(100);
v2.push_back(200);
v2.push_back(300);
v2.push_back(400);
v2.push_back(500);
vector<int> v3;
v3.push_back(1000);
v3.push_back(2000);
v3.push_back(3000);
v3.push_back(4000);
v3.push_back(5000);
vector<vector<int>> v;
v.push_back(v1);
v.push_back(v2);
v.push_back(v3);
vector<vector<int>>::iterator it=v.begin();
for(;it!=v.end();it++)
{
        //*it == vector<int>
        vector<int>::iterator mit=(*it).begin();
        for(;mit!=(*it).end(); mit++)
        {
                //*mit==int
                cout<<*mit<<" ";
        }
        cout<<endl;
}
}

 deque

deque是一种双向开口的连续线性空间,所谓的双向开口,意思是可以在头尾两端分别做元素的插入和删除操作

数据结构:数组

与vector的区别:

        1,deque允许使用常数项时间对头端进行元素的插入和删除

        2,deque没有容量的概念,因为他是动态的以分段连续空间组合而成,随时可以增加一段新的空间并连接起来

                        

// 构造函数
deque<T> deqT;// 默认构造形式
deque(beg, end);// 构造函数将 [beg, end) 区间中的元素拷贝给本身。
deque(n, elem);// 构造函数将 n elem 拷贝给本身。
deque(const deque &deq);// 拷贝构造函数
// 赋值操作
assign(beg, end);// [beg, end) 区间中的数据拷贝赋值给本身。
assign(n, elem);// n elem 拷贝赋值给本身。
deque& operator=(const deque &deq); // 重载等号操作符
swap(deq);// deq 与本身的元素互换
// 大小操作
deque.size();// 返回容器中元素的个数
deque.empty();// 判断容器是否为空
deque.resize(num);// 重新指定容器的长度为 num, 若容器变长,则以默认值填充新
位置。如果容器变短,则末尾超出容器长度的元素被删除。
deque.resize(num, elem); // 重新指定容器的长度为 num, 若容器变长,则以 elem
值填充新位置 , 如果容器变短,则末尾超出容器长度的元素被删除。
// 双端插入和删除操作
push_back(elem);// 在容器尾部添加一个数据
push_front(elem);// 在容器头部插入一个数据
pop_back();// 删除容器最后一个数据
pop_front();// 删除容器第一个数据
// 数据存取
at(idx);// 返回索引 idx 所指的数据,如果 idx 越界,抛出 out_of_range
operator[];// 返回索引 idx 所指的数据,如果 idx 越界,不抛出异常,直接出
错。
front();// 返回第一个数据。
back();// 返回最后一个数据
// 插入操作
insert(pos,elem);// pos 位置插入一个 elem 元素的拷贝,返回新数据的位置。
insert(pos,n,elem);// pos 位置插入 n elem 数据,无返回值。
insert(pos,beg,end);// pos 位置插入 [beg,end) 区间的数据,无返回值。
// 删除操作
clear();// 移除容器的所有数据
erase(beg,end);// 删除 [beg,end) 区间的数据,返回下一个数据的位置。
erase(pos);// 删除 pos 位置的数据,返回下一个数据的位置。

stack

栈(先进后出),单项开口,没有迭代器

构造函数
stack<T> stkT;//stack 采用模板类实现, stack 对象的默认构造形式:
stack(const stack &stk);// 拷贝构造函数
赋值操作
stack& operator=(const stack &stk);// 重载等号操作符
数据存取操作
push(elem);// 向栈顶添加元素
pop();// 从栈顶移除第一个元素
top();// 返回栈顶元素
大小操作
empty();// 判断堆栈是否为空
size();// 返回堆栈的大小

queue

队列(先进先出),双向开口,没有迭代器

对头:出数据

队尾:入数据

构造函数
queue<T> queT;//queue 采用模板类实现, queue 对象的默认构造形式:
queue(const queue &que);// 拷贝构造函数
存取、插入和删除操作
push(elem);// 往队尾添加元素
pop();// 从队头移除第一个元素
back();// 返回最后一个元素
front();// 返回第一个元素
赋值操作
queue& operator=(const queue &que);// 重载等号操作符
大小操作
empty();// 判断队列是否为空
size();// 返回队列的大小

list

基于双向链表,离散存储的,双向迭代器,元素可重复

数据结构:链表


双向迭代器:可以++,--,但是不能+,-

  

构造函数
        list<T> lstT;//list 采用采用模板类实现 , 对象的默认构造形式:
        list(beg,end);//构造函数将 [beg, end) 区间中的元素拷贝给本身。
        list(n,elem);//构造函数将 n elem 拷贝给本身。
        list(const list &lst);//拷贝构造函数。
数据元素插入和删除操作
        push_back(elem);//在容器尾部加入一个元素
        pop_back();//删除容器中最后一个元素
        push_front(elem);//在容器开头插入一个元素
        pop_front();//从容器开头移除第一个元素
        insert(pos,elem);//在 pos 位置插 elem 元素的拷贝,返回新数据的位置。
        insert(pos,n,elem);//在 pos 位置插入 n elem 数据,无返回值。
        insert(pos,beg,end);//在 pos 位置插入 [beg,end) 区间的数据,无返回值。
        clear();//移除容器的所有数据
        erase(beg,end);//删除 [beg,end) 区间的数据,返回下一个数据的位置。
        erase(pos);//删除 pos 位置的数据,返回下一个数据的位置。
        remove(elem);//删除容器中所有与 elem 值匹配的元素。
大小操作
        size();//返回容器中元素的个数
        empty();//判断容器是否为空
        resize(num);//重新指定容器的长度为 num ,若容器变长,则以默认值填充新位置。如果容器变短,则末尾超出容器长度的元素被删除。
        resize(num, elem);//重新指定容器的长度为 num, 若容器变长,则以 elem 值填充新位置。如果容器变短,则末尾超出容器长度的元素被删除。
赋值操作
        assign(beg, end);//将 [beg, end) 区间中的数据拷贝赋值给本身。
        assign(n, elem);//将 n elem 拷贝赋值给本身。
        list& operator=(const list &lst);//重载等号操作符
        swap(lst);//将 lst 与本身的元素互换。
数据的存取
        front();//返回第一个元素。
        back();//返回最后一个元素。
反转排序
        reverse();//反转链表,比如 lst 包含 1,3,5 元素,运行此方法后, lst 就包含 5,3,1 元素。
        sort(); //list 排序

set/multiset

set特点

Set 的特性是。所有元素都会根据元素的键值自动被排序。
set 容器的键值和实值 是同一个值。
Set 不允许两个元素 有相同的键值。
Set 容器的迭代器 是只读迭代器。 插入数据后 不允许修改 set 的键值。
数据结构 : 红黑树
注意 :
        如果存入的值大于原有的值, 此时 x > y 为真 , 存入的值在原有值左边
        如果存储的值小于原有的值, 此时 x > y 为假 , 交换在比较
        如果交换后, 存储的值为 y, 原有值的为 x, 此时 x > y 为真 , 存入的值不应该在原有值左边
        如果交换后, 存储的值为 y, 原有值的为 x, 此时 x > y 为假 , 此时证明不符合其存储原则
multiset特点
构造函数
set<T> st;//set 默认构造函数:
mulitset<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 的元素。
查找操作
find(key);// 查找键 key 是否存在 , 若存在,返回该键的元素的迭代器;若不存在,返回 set.end();
count(key);// 查找键 key 的元素个数
lower_bound(keyElem);// 下限返回第一个 key>=keyElem 元素的迭代器。
upper_bound(keyElem);// 上限返回第一个 key>keyElem 元素的迭代器。
equal_range(keyElem);// 返回容器中 key keyElem 相等的上下限的两个迭代器。

 map/multimap

map概述

键值对的形式存储数据 , 一个键值对称为一个对组
这一对值可以具有不同的数据类型,两个值可以分别用 pair( 对组 ) 的两个公共的成员
变量 first( ) second( ) 访问。
不允许键重复
multimap概述
允许键重复​​​​​​​
map 构造函数
map<T1, T2> mapTT;//map 默认构造函数 :
        T1:键的数据类型 , 要有可比较性 , 基本数据类型都有可比性
        T2:值的数据类型
map(const map &mp);// 拷贝构造函数
map 赋值操作
map& operator=(const map &mp);// 重载等号操作符
swap(mp);// 交换两个集合容器
map 大小操作
size();// 返回容器中元素的数目
empty();// 判断容器是否为空
map 插入数据元素操作
map.insert(...); // 往容器插入元素,返回 pair<iterator,bool>
map 删除操作
clear();// 删除所有元素
erase(pos);// 删除 pos 迭代器所指的元素,返回下一个元素的迭代器。
erase(beg,end);// 删除区间 [beg,end) 的所有元素 ,返回下一个元素的迭代器。
erase(keyElem);// 删除容器中 key keyElem 的对组。
map 查找操作
find(key);// 查找键 key 是否存在 , 若存在,返回该键的元素的迭代器;若不存在,返回 map.end();
count(keyElem);// 返回容器中 key keyElem 的对组个数。对 map 来说,要么是 0 ,要么是 1 。对 multimap 来说,值可能大于 1
lower_bound(keyElem);// 返回第一个 key>=keyElem 元素的迭代器。
upper_bound(keyElem);// 返回第一个 key>keyElem 元素的迭代器。
equal_range(keyElem);// 返回容器中 key keyElem 相等的上下限的两个迭代
器。

 总结

vector 单端动态数组 随机访问迭代器 ( 重点 )
比如软件历史操作记录的存储,我们经常要查看历史记录,比如上一次的记录,上上次
的记录,但却不会去删除记录,因为记录是事实的描述。
        数据结构: 数组
deque :双端动态数组 随机访问迭代器
deque 的使用场景:比如排队购票系统,对排队者的存储可以采用 deque ,支持头端
的快速移除,尾端的快速添加
stack 栈容器 没有迭代器 先进后出
queue 队列容器 没有迭代器 先进先出
list 链表容器 双向迭代器 ( 重点 )
比如公交车乘客的存储,随时可能有乘客下车,支持频繁的不确实位置元素的移除插入
        数据结构: 双链表
set 容器 只有键值 键值不能重复 自动排序 只读迭代器
比如对手机游戏的个人得分记录的存储,存储要求从高 分到低分的顺序排列。
        数据结构: 红黑树
map 容器: 键值 - 实值成对出现 键值不能重复 自动排序 只读迭代器 ( 重点 )
比如按 ID 号存储十万个用户,想要快速要通过 ID 查找对应的用户。
        数据结构: 红黑树

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/60316.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

嵌入式实验报告:家用计时器

实验目的和要求 1、实验目的 掌握STM32串口通信原理。学习编程实现STM32的UART通信掌握STM32中断程序设计流程。熟悉STM32固件库的基本使用。熟悉STM32定时器中断设计流程。2、实验要求 设计一个家用计时器,其功能如下: 利用串口设置计时时间,格式:XX:XX:X 例如01:59:…

阿里巴巴官方「SpringCloudAlibaba全彩学习手册」限时开源!

最近我在知乎上看过的一个热门回答&#xff1a; 初级 Java 开发面临的最大瓶颈在于&#xff0c;脱离不出自身业务带来的局限。日常工作中大部分时间在增删改查、写写接口、改改 bug&#xff0c;久而久之就会发现&#xff0c;自己的技术水平跟刚工作时相比没什么进步。 所以我们…

低成本搭建单相220V转三相380V变频器配滤波器的转换器

一、单相转三相的迫切需求 在许多工业和商业场景中&#xff0c;三相电源因其高效、稳定的特性而被广泛应用。然而&#xff0c;并非所有场所都能提供三相电源&#xff0c;尤其是在一些老旧建筑或偏远地区&#xff0c;单相220V电源更为常见。这就迫切需要我们找到一种有效的转换…

如何从 VMware 官网下载最新版本的 VMware Workstation

文章目录 📖 介绍 📖🏡 演示环境 🏡📒 下载VMware 📒📝 操作步骤🎈 获取方式 🎈⚓️ 相关链接 ⚓️📖 介绍 📖 你是否曾尝试从 VMware 官网下载 VMware Workstation,但总是被繁杂的选择和复杂的操作困扰?VMware 提供的产品种类繁多,而且官网页面设计复…

数据结构_图的遍历

深度优先搜索遍历 遍历思想 邻接矩阵上的遍历算法 void Map::DFSTraverse() {int i, v;for (i 0; i < MaxLen; i){visited[i] false;}for (i 0; i < Vexnum; i){// 如果顶点未访问&#xff0c;则进行深度优先搜索if (visited[i] false){DFS(i);}}cout << endl…

基于CVE安全公告号,全面修复麒麟ARM系统OpenSSH漏洞

前言&#xff1a;负责的其中一个从0开始搭建的某生产项目上线前需要做青藤安全扫描&#xff0c;过了后才允许上线&#xff0c;该项目从操作系统、中间件、数据库、容器等全国产信创化&#xff0c;公司公告为CVE安全公告号&#xff0c;而修复漏洞的责任归我&#xff0c;需要根据…

python成绩分级 2024年6月python二级真题 青少年编程电子学会编程等级考试python二级真题解析

目录 python成绩分级 一、题目要求 1、编程实现 2、输入输出 二、算法分析 三、程序代码 四、程序说明 五、运行结果 六、考点分析 七、 推荐资料 1、蓝桥杯比赛 2、考级资料 3、其它资料 python成绩分级 2024年6月 python编程等级考试二级编程题 一、题目要求 …

vulnhub靶场-tomato

arp-scan -l用arp-scan探测一下网段内目标靶机的IP arp-scan 是一款轻量级的arp扫描工具&#xff0c;会解析mac地址&#xff0c;就是想 局域网 中所有可能的ip地址发出arp请求包&#xff0c;如果得到arp回应&#xff0c;就证明了局域网中某主机使用了该ip。 nmap扫一下c段 nma…

JavaScript中的执行顺序

分析下面JavaScript代码的执行顺序&#xff1a; <script>setTimeout(() > console.log(代码开始执行), 0)new Promise((resolve, reject) > {console.log(开始for循环);for (let i 0; i < 10000; i) {i 99 && resolve()}}).then(() > console.log(…

【天壤智能-注册安全分析报告-无验证纯IP限制存在误拦截隐患】

前言 由于网站注册入口容易被机器执行自动化程序攻击&#xff0c;存在如下风险&#xff1a; 暴力破解密码&#xff0c;造成用户信息泄露&#xff0c;不符合国家等级保护的要求。短信盗刷带来的拒绝服务风险 &#xff0c;造成用户无法登陆、注册&#xff0c;大量收到垃圾短信的…

大数据实验4-HBase

一、实验目的 阐述HBase在Hadoop体系结构中的角色&#xff1b;能够掌握HBase的安装和配置方法熟练使用HBase操作常用的Shell命令&#xff1b; 二、实验要求 学习HBase的安装步骤&#xff0c;并掌握HBase的基本操作命令的使用&#xff1b; 三、实验平台 操作系统&#xff1…

内网安全隧道搭建-ngrok-frp-nps-sapp

1.ngrok 建立内网主机与公网跳板机的连接&#xff1a; 内网主机为客户机&#xff1a; 下载客户端执行 2.frp &#xff08;1&#xff09;以下为内网穿透端口转发 frp服务端配置&#xff1a; bindPort 为frp运行端口 服务端运行 ./frps -c frps.ini frp客户端配置&#xf…

三十一、构建完善微服务——API 网关

一、API 网关基础 系统拆分为微服务后&#xff0c;内部的微服务之间是互联互通的&#xff0c;相互之间的访问都是点对点的。如果外部系统想调用系统的某个功能&#xff0c;也采取点对点的方式&#xff0c;则外部系统会非常“头大”。因为在外部系统看来&#xff0c;它不需要也没…

前端:HTML (学习笔记)【1】

一&#xff0c;网络编程的三大基石 1&#xff0c;URL &#xff08;1&#xff09;url —— 统一资源定位符&#xff1a; 网址——整个互联网中可以唯一且准确的确定一个资源的位置。 【项目外】 网址——https://www.baidu.com/ …

实验室管理现代化:Spring Boot技术方案

4系统概要设计 4.1概述 本系统采用B/S结构(Browser/Server,浏览器/服务器结构)和基于Web服务两种模式&#xff0c;是一个适用于Internet环境下的模型结构。只要用户能连上Internet,便可以在任何时间、任何地点使用。系统工作原理图如图4-1所示&#xff1a; 图4-1系统工作原理…

如何在 Microsoft Edge 中设置代理: 快速而简单的方法

你知道在 Microsoft Edge 中设置代理可以大大提升浏览体验吗&#xff1f;无论您是想提高隐私保护、访问受地理位置限制的内容&#xff0c;还是想更高效地浏览网页&#xff0c;代理服务器都能改变一切。 本指南将介绍如何在 Microsoft Edge 中设置代理&#xff0c;解决常见的代…

Excel如何批量导入图片

这篇文章将介绍在Excel中如何根据某列数据&#xff0c;批量的导入与之匹配的图片。 准备工作 如图&#xff0c;我们准备了一张员工信息表以及几张员工的照片 可以看到&#xff0c;照片名称是每个人的名字&#xff0c;与Excel表中的B列&#xff08;姓名&#xff09;对应 的卢易…

【操作系统】操作系统的特征

操作系统的七个基本特征 并发性&#xff08;Concurrence&#xff09; 并发性是指操作系统在同一时间间隔内执行和调度多个程序的能力&#xff0c;提高资源利用率和系统效率。尽管多个任务可能在同一时刻看似同时进行&#xff0c;但实际上&#xff0c;CPU在多个任务之间快速切…

iPhone 17 Air看点汇总:薄至6mm 刷新苹果轻薄纪录

我们姑且将这款iPhone 17序列的超薄SKU称为“iPhone 17 Air”&#xff0c;Jeff Pu在报告中提到&#xff0c;我同意最近关于 iPhone 17超薄机型采用6 毫米厚度超薄设计的传言。 如果这一测量结果被证明是准确的&#xff0c;那么将有几个值得注意的方面。 首先&#xff0c;iPhone…

springboot嗨玩旅游网站

摘 要 嗨玩旅游网站是一个专为旅行爱好者打造的在线平台。我们提供丰富多样的旅游目的地信息&#xff0c;包括景点信息、旅游线路、商品信息、社区信息、活动推广等&#xff0c;帮助用户轻松规划行程。嗨玩旅游网站致力于为用户提供便捷、实用的旅行服务&#xff0c;让每一次旅…