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;自己的技术水平跟刚工作时相比没什么进步。 所以我们…

理解 Python 中的 self 它的作用与在类中的应用

理解 Python 中的 self: 它的作用与在类中的应用 在 Python 中&#xff0c;self 是一个约定俗成的关键字&#xff0c;用于指代类的当前实例。它是实例方法中的第一个参数&#xff0c;通过 self 可以访问类的属性和其他方法。虽然这个词不是 Python 语法的强制部分&#xff0c;…

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

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

多线程并发造成的数据重复问题解决方案参考(笔记记录)

一、添加 MySQL 组合唯一索引&#xff0c;需要注意什么坑&#xff1f; 在 MySQL 中&#xff0c;创建组合唯一索引&#xff08;Composite Unique Index&#xff09;时&#xff0c;需要注意以下一些容易踩的坑&#xff1a; 1. 字段顺序影响索引使用 问题&#xff1a;组合唯一索…

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

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

【人工智能】深度学习入门:用TensorFlow实现多层感知器(MLP)模型

《Python OpenCV从菜鸟到高手》带你进入图像处理与计算机视觉的大门! 多层感知器(MLP)是一种基础的神经网络结构,广泛应用于分类和回归任务。作为深度学习的重要组成部分,理解并实现MLP是学习更复杂神经网络模型的基础。本文将介绍多层感知器的核心概念、数学原理,并使用…

C#无符号整数类型详解:声明、使用及注意事项

在C#编程语言中&#xff0c;无符号整数类型&#xff08;Unsigned Integer Types&#xff09;指的是那些只能表示非负整数的数据类型。与有符号整数类型&#xff08;Signed Integer Types&#xff09;不同&#xff0c;无符号整数类型不包括负数&#xff0c;因此它们可以表示的正…

Vue3中的TSX

在 Vue 3 中&#xff0c;有两种声明组件的方式 常用的Template方式TSX (TypeScript JSX) &#xff0c;tsx是一种声明组件的灵活方式&#xff0c;特别适合在动态渲染和复杂逻辑场景中。 一、TSX 的特点 TSX 是 JSX 的扩展&#xff0c;允许使用 TypeScript 的强类型特性。更适…

SQLite Truncate Table

SQLite Truncate Table SQLite 是一种轻量级的数据库管理系统&#xff0c;广泛用于各种应用程序中。在数据库管理中&#xff0c;有时候需要快速删除表中的所有数据&#xff0c;这时就可以使用 TRUNCATE TABLE 命令。然而&#xff0c;SQLite 与其他数据库管理系统&#xff08;如…

数据结构_图的遍历

深度优先搜索遍历 遍历思想 邻接矩阵上的遍历算法 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…

Spring Boot核心概念:日志管理

日志记录是软件开发的重要组成部分&#xff0c;它帮助开发人员了解应用程序运行时的状态&#xff0c;以及在故障排查和性能监控时提供关键信息。Spring Boot通过提供默认的日志配置&#xff0c;简化了日志管理。 Spring Boot默认日志框架 Spring Boot默认使用Logback作为日志…

基于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;大量收到垃圾短信的…

SQLAlchemy,ORM的Python标杆!

嗨&#xff0c;Python的小伙伴们&#xff01;今天咱们来了解 SQLAlchemy&#xff0c;这可是对象关系映射&#xff08;ORM&#xff09;里的超级标杆哦&#xff01;它就像一座神奇的桥梁&#xff0c;能让我们用 Python 代码轻松地和数据库打交道&#xff0c;不用写复杂的 SQL 语句…

前端测试工具(Jest与Mock)

Jest 工具详解&#xff1a;从安装到使用** Jest 是一个流行的 JavaScript 测试框架&#xff0c;广泛用于 React 应用及其他 JavaScript 项目的测试。它是由 Facebook 创建的&#xff0c;具有简单、快速、功能强大的特点。 一、Jest 的安装 1.1 环境准备 Jest 需要运行在 Nod…

Makefile 之 wordlist

wordlist $(wordlist <s>,<e>,<text> ) 名称&#xff1a;取单词串函数——wordlist。 功能&#xff1a;从字符串<text>中取从<s>开始到<e>的单词串。<s>和<e>是一个数字。 返回&#xff1a;返回字符串<text>中从…