C++ STL基础

一.STL基本概念

1.STL基本概念

-- STL(standard template library,标准模板库)

-- STL从广义上分为:容器(container)  算法(algorithm)  迭代器(iterator)

-- 容器 和 算法 之间通过 迭代器 进行无缝连接

-- STL几乎所有的代码都采用了模板类或者模板函数

2.STL六大组件

分别是:容器、算法、迭代器、仿函数、适配器(配接器)、空间配置器

容器:各种数据结构,如vector、list、deque、set、map等,用来存放数据

算法:各种常用的算法,如sort、find、copy、for_each等

迭代器:扮演了容器和算法之间胶合剂

仿函数:行为类似函数,可作为算法的某种策略

适配器:一种用来修饰容器或者仿函数或迭代器接口的东西

空间配置器:负责空间的配置和管理

3.STL中的容器、算法、迭代器

1.容器:STL容器就是将运用最广泛的一些数据结构实现出来

常用的数据结构:数组、链表、树、栈、队列、集合、映射表等

容器分为:序列式容器和关联式容器

序列式容器:强调值的排序,序列式容器中的每个元素均有固定的位置

关联式容器:二叉树结构,各元素之间没有严格的物理上的顺序关系

2.算法:有限的步骤,解决逻辑或数学上的问题,这一门学科叫做算法(algorithms)

算法分为:质变算法和非质变算法

质变算法:运算过程中会更改区间内的元素的内容,如拷贝、替换、删除等

非质变算法:运算过程中不会更改区间内的元素的内容,如查找、计数、遍布等

3.迭代器:容器和算法之间的粘合剂,提供一种方法,使之能够依序访问某个容器所含的各个元素,而又无需暴露该容器的内部表示方式。

每个容器都有自己专属的迭代器

迭代器使用非常类似于指针,初学阶段可以先理解迭代器为指针

迭代器种类:

常用的容器中迭代器种类为双向迭代器和随机访问迭代器。

4.容器算法迭代器初识

如下,使用迭代器遍历v1

void test() {
    //创建一个vector容器
    vector<int> v1;

    //向容器中插入数据
    v1.push_back(1);
    v1.push_back(2);
    v1.push_back(3);
    v1.push_back(4);

    //通过迭代器访问容器中的数据
    vector<int>::iterator itBegin = v1.begin();//起始迭代器,指向容器中第一个元素
    vector<int>::iterator itEnd = v1.end();//结束迭代器,指向容器中最后一个元素的下一个位置

    //第一种遍历方式
    while (itBegin != itEnd) {
        cout << *itBegin << endl;
        itBegin++;
    }

    //第二种遍历方式
    for (vector<int>::iterator it = v1.begin(); it != v1.end(); it++) {
        cout << *it << endl;
    }

}

二.常用容器

1.string容器

1.1基本概念

本质: string是C++风格的字符串,本质上是一个类

string与char*的区别:

-- char*是一个指针

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

特点:

string类内部封装了很多成员方法,如查找find、拷贝copy等

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

1.2string构造函数

构造函数原型:

string();                //创建一个空的字符串,如string s;
string(const char* s);   //使用字符串s初始化;
string(const string& s); //使用一个string对象初始化另一个string对象
string(const string& s, int begin, int len);//将字符串s从下标begin开始、长度为len的部分作为字符串初值
string(int n, char c);   //使用n个字符c初始化

示例:

string s1;                 //生成空字符串
string s2("12345");        //生成"12345"的复制品
string s3("12345", 0, 3);  //结果为"123"
string s4(5, '1');         //结果为"11111"

string的多种构造函数没有可比性,灵活使用即可

1.3string赋值操作

功能:给string字符串赋值

函数原型:

string& operator=(const char* s);    //char*类型字符串赋值给当前字符串
string& operator=(const string& s);  //把字符串s赋值给当前字符串
string& assign(const char* s);       //把字符串s赋值给当前字符串
string& assign(const char* s,int n); //把字符串s的前n个字符赋值给当前字符串
string& assign(const string& s);     //
string& assign(int n,char c);        //用n个字符c赋值给当前字符串

string的赋值方式有很多,=是比较实用的

1.4string的大小和容量

功能:获取对象的大小和容量

函数原型:

int size()
int length()
//返回string对象的字符个数,他们执行效果相同。

int capacity()//重新分配内存之前,string对象能包含的最大字符数

示例:

    string s("1234567");
    cout << s.size() << endl;      //输出7
    cout << s.length() << endl;    //输出7
    cout << s.capacity() << endl;  //输出15

1.5string字符串拼接

功能:实现在字符串末尾拼接字符串

函数原型:

string& operator+=(const char* s);
string& operator+=(const string& s);
string& append(const char* s);
string& append(const char* s, int n);            //把字符串s的前n个字符连接到当前字符串末尾
string& append(const string& s);
string& append(const string& s, int pos, int n); //把字符串s从pos开始的n个字符连接到当前字符串末尾

1.6string查找和替换

功能:

-- 查找:查找指定字符串是否存在

-- 替换:在指定的位置替换字符串

函数原型:

int find(const string& s, int pos=0) const;       //查找字符串s第一次出现的位置,从pos开始找
int find(const string& s, int pos=0, int n) const;//从pos位置查找字符串s的前n个字符第一次出现的位置
int find(const char c, int pos=0) const;          //查找字符c第一次出现的的位置
int rfind(const string& s, int pos=npos) const;   //查找字符串s最后一次出现的位置,从pos开始找
int rfind(const char c, int pos=0) const;         //查找字符c最后一次出现的位置

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

示例:

    string s1 = "11abc11";
    cout << s1.find("11")<<endl;    //输出0
    cout << s1.rfind("11") << endl; //输出5

    string s2 = "aabbccdd";
    s2.replace(2, 2, "1111");
    cout << s2 << endl;             //输出aa1111ccdd

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

-- find找不到则返回一个很大的数,表示找不到,在无穷远

1.7字符串比较

功能:字符串之间的比较

比较方式:按照字符的ASCII码比较

= 返回 0        > 返回 1        < 返回 -1

函数原型:

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

示例:

    string s1 = "aa";
    string s2 = "ab";

    cout << s1.compare(s2)<<endl; //输出-1

1.8string字符存取

功能:对单个字符进行读或写的操作

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

1.9string插入和删除

功能:对字符串进行插入和删除字符操作

函数原型:

string& insert(int pos, const string& s); //插入字符串
string& insert(int pos, int n, char c);   //在指定位置插入n个字符c
string& erase(int pos, int n=npos);       //删除从pos开始的n个字符

示例:

    string s1 = "12345";
    s1.insert(1, "000");
    cout << s1 << endl;     //输出10002345

    string s2 = "12345";
    s2.erase(1);
    cout << s2 << endl;     //输出1

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

1.10string子串

函数原型:

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

示例:

    string s1 = "12345";
    string s2 = s1.substr(1, 3);
    cout << s2 << endl;     //输出234

2.vector容器

2.1基本概念

功能:与数组非常相似,也称为单端数组

与普通数组的区别:数组是静态空间,而vector可以动态扩展

动态扩展:并不是在原空间之后续接新空间,而是找更大的内存空间,然后将原数据拷贝至新空间,释放原空间

vector容器的迭代器是支持随机访问的迭代器,即它的迭代器可以跳跃式的访问

2.2vector构造函数

功能:创建一个vector容器

函数原型:

vector<T> v;                //采用模板实现类实现,默认构造函数
vector(v.begin(),v.end());  //将v[ begin(),end() )区间中的元素拷贝给本身(区间前闭后开)
vector(n,elem);             //构造函数将n个elem拷贝给本身
vector(const vector& v);    //拷贝构造函数

示例:

//vector<int> 输出
void Print_vector_int(vector<int>& v) {
    for (vector<int>::iterator it = v.begin(); it != v.end(); it++) {
        cout << *it << ' ';
    }
    cout << endl;
}

//vector构造
void test01() {

    vector<int> v1; //默认构造

    //向容器中插入数据
    v1.push_back(1);
    v1.push_back(2);
    v1.push_back(3);
    v1.push_back(4);
    v1.push_back(5);

    Print_vector_int(v1);
    //输出1 2 3 4 5

    vector<int> v2(v1.begin(), v1.end());//通过区间方式构造
    Print_vector_int(v2);
    //输出1 2 3 4 5

    vector<int> v3(5, 1);//n个elem方式构造
    Print_vector_int(v3);
    //输出1 1 1 1 1 

    vector<int> v4(v3);//拷贝构造
    Print_vector_int(v4);
    //输出1 1 1 1 1 
}

2.3vector赋值操作

功能:给vector容器进行赋值

函数原型:

vector& operator=(const vector& v); //重载等号运算符
assign (begin, end);                //将[begin,end)区间中的数据拷贝赋值给本身
assign (n, elem);                   //将n个elem拷贝赋值给本身

示例:

//vector赋值
void test02() {
    vector<int> v1; //默认构造

    //向容器中插入数据
    v1.push_back(1);
    v1.push_back(2);
    v1.push_back(3);
    v1.push_back(4);
    v1.push_back(5);

    vector<int> v2 = v1;//等号赋值
    Print_vector_int(v2);
    //输出1 2 3 4 5 

    vector<int> v3;
    v3.assign(v1.begin(), v1.end());
    Print_vector_int(v3);
    //输出1 2 3 4 5

}

2.4vector容量和大小

功能:对vector容器的容量和大小操作

函数原型:

empty();             //判断容器是否为空
capacity();          //容器的容量
size();              //返回容器中元素的个数
resize(int num);     //重新指定容器的长度为num,
                     //若容器变长,则以默认值填充新位置,
                     //若容器变短,则末尾超出容器长度的元素被删除
resize(int num, elem)//同上,以num填充新位置

示例:

//vector的容量和大小
void test03() {
    vector<int> v1;
    for (int i = 0; i != 10; i++) {
        v1.push_back(i);
    }

    Print_vector_int(v1);
    //输出0 1 2 3 4 5 6 7 8 9

    if (!v1.empty()) {//若v1不为空
        cout << v1.capacity() << endl; //输出13
        cout << v1.size() << endl;      //输出10
    }

    //重新指定大小
    v1.resize(15);//如果重新指定的比原来长了,默认使用0填充,利用重载版本可以指定填充值
    Print_vector_int(v1); 
    //输出0 1 2 3 4 5 6 7 8 9 0 0 0 0 0
    cout << v1.capacity() << endl;//输出19


    v1.resize(5);//如果指定的比原来短了,超出部分会删除掉
    Print_vector_int(v1);
    //输出 0 1 2 3 4 
    cout << v1.capacity() << endl;//输出19

}

2.5vector插入和删除

功能:对vector容器进行插入和删除

函数原型:

push_back(elem);                            //尾部插入元素
pop_back();                                 //删除尾部元素
insert(const_iterator pos, elem);           //迭代器指向位置pos插入元素elem
insert(const_iterator pos, int count, elem);//迭代器指向位置pos插入count个元素elem
erase(const_iterator);                      //删除迭代器指向的元素
erase(const_iterator start, const_iterator end);//删除[start,end)区间的元素
clear();                                    //删除容器中所有元素

示例:

void test04() {
    vector<int> v1;
    for (int i = 0; i != 10; i++) {
        v1.push_back(i); //push_back尾插
    }
    Print_vector_int(v1);
    //输出0 1 2 3 4 5 6 7 8 9

    v1.pop_back(); //pop_back尾删,删去9

    v1.insert(v1.begin(), 100); //insert插入
    Print_vector_int(v1);
    //输出100 0 1 2 3 4 5 6 7 8

    v1.erase(v1.begin());//erase删除
    Print_vector_int(v1);
    //输出 0 1 2 3 4 5 6 7 8

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

2.6vector数据存取

功能:对vector中的数据进行存取操作

函数原型:

at(int index);            //返回索引index所指的数据
operator[] (int index);   //返回索引index所指的数据
front();                  //返回容器中的第一个数据元素
back();                   //返回容器中的最后一个数据元素

示例:

//数据存取
void test05() {
    vector<int> v1;
    for (int i = 0; i != 10; i++) {
        v1.push_back(i); //push_back尾插
    }

    for (int i = 0; i < v1.size(); i++) {
        cout << v1[i] << ' ';//输出 0 1 2 3 4 5 6 7 8 9
    }
    cout << endl;

    for (int i = 0; i < v1.size(); i++) {
        cout << v1.at(i) << ' ';//输出 0 1 2 3 4 5 6 7 8 9
    }
    cout << endl;

    cout << v1.front() << endl;//输出0
    cout << v1.back() << endl;//输出9
}

2.7vector互换容器

功能:实现两个容器对象内元素互换

函数原型:

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

swap互换的两个对象不仅值互换,capacity值也会互换

示例:

//互换容器
void test06() {
    vector<int> v1,v2;
    for (int i = 0; i != 5; i++) {
        v1.push_back(i+1);   
    }
    for (int i = 0; i != 10; i++) {
        v2.push_back(i+1);
    }
    Print_vector_int(v1);//输出1 2 3 4 5 
    Print_vector_int(v2);//输出1 2 3 4 5 6 7 8 9 10
    cout << v1.capacity()<<endl;//输出6
    cout << v2.capacity()<<endl;//输出13

    v1.swap(v2);//互换容器
    Print_vector_int(v1);//输出1 2 3 4 5 6 7 8 9 10
    Print_vector_int(v2);//输出1 2 3 4 5 
    cout << v1.capacity() << endl;//输出13
    cout << v2.capacity() << endl;//输出6

}

巧用swap可以收缩内存空间

//巧用swap收缩内存
void test() {
    vector<int> v3;
    for (int i = 0; i != 10000; i++) {
        v3.push_back(i + 1);
    }

    cout << v3.capacity() << endl; //输出12138
    cout << v3.size() << endl; //输出10000

    v3.resize(5);
    cout << v3.capacity() << endl; //输出12138
    cout << v3.size() << endl; //输出5

    //收缩内存
    vector<int>(v3).swap(v3);//拷贝构造创建一个匿名对象,但创建的匿名的capacity值只有5,然后swap,之后匿名对象自动销毁
   
    cout << v3.capacity() << endl;//输出5
    cout << v3.size() << endl;//输出5
}

2.8vector预留空间

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

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

函数原型:

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

示例:

//容器预留空间
void test07() {
    vector<int> v1;
    int count = 0;//统计一共动态开辟了多少次内存
    int* p = nullptr;
    
    for (int i = 0; i < 100000; i++) {
        v1.push_back(i);
        if (p != &v1[0]) {//动态开辟一次内存,count+一次
            ++count;
            p = &v1[0];
        }
    }
    cout << count << endl;//输出30,即动态开辟了29次


    vector<int> v2;
    count = 0;
    p = nullptr;
    v2.reserve(100000);

    for (int i = 0; i < 100000; i++) {
        v2.push_back(i);
        if (p != &v2[0]) {//动态开辟一次内存,count+一次
            ++count;
            p = &v2[0];
        }
    }
    cout << count << endl;//输出1,即动态开辟了0次
}

3.deque容器

3.1基本概念

功能:双端数组,可以对头端和尾端进行插入删除操作

deque与vector的区别:

-- vector对于头部的插入删除效率太低,数据量越大,效率越低。deque相对而言,对头部的插入     删除速度会比vector快

-- vector访问元素时的速度回避deque快,这与两者的内部实现有关

deque内部原理:

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

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

vector容器的迭代器是支持随机访问的迭代器,即它的迭代器可以跳跃式的访问

3.2deque构造函数

功能:deque容器构造

函数原型:

deque<T> d;                //采用模板实现类实现,默认构造函数
deque(d.begin(),d.end());  //将d[ begin(),end() )区间中的元素拷贝给本身(区间前闭后开)
deque(n,elem);             //构造函数将n个elem拷贝给本身
deque(const deque& d);    //拷贝构造函数

示例:

//打印deque
void printDeque(const deque<int>& d) {
    for (deque<int>::const_iterator it = d.begin(); it != d.end(); it++) {
        cout << *it << ' ';
    }
    cout << endl;
}
 
void test08() {
    deque<int> d(5, 10);
    printDeque(d);
    //输出10 10 10 10 10
}

3.3deque赋值操作

功能:给deque容器进行赋值

函数原型:

deque& operator=(const deque& d);    //重载等号运算符
assign(beg,end);                     //将[beg,end)区间中的数据拷贝赋值给自身
assign(n,elem);                      //将n个elem拷贝赋值给自身

3.4deque大小操作

功能:对deque容器的大小进行操作

函数原型:

empty();                //判断容器是否为空
size();                 //返回容器中元素的个数
resize(int num);        //同vector的resize
resize(int num, elem);

deque无capacity。

3.5deque插入和删除

功能:向deque容器中插入和删除数据

函数原型:

//两端插入删除:
push_back(elem);        //尾部插入元素
push_front(elem);       //头部插入元素
pop_back();             //尾部删除元素
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位置的数据,返回下一个数据的地址

3.6deque数据存取

功能:对deque中的数据进行存取

函数原型:

at(int index);            //返回索引index所指的数据
operator[] (int index);   //返回索引index所指的数据
front();                  //返回容器中的第一个数据元素
back();                   //返回容器中的最后一个数据元素

3.7deque排序

利用算法实现对deque容器进行排序

算法:

使用时需要包含头文件algorithm

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

示例:

//deque排序
void test09() {
    deque<int> d;
    d.push_back(1);//尾插
    d.push_back(2);
    d.push_back(3);
    d.push_front(10);//头插
    d.push_front(20);
    d.push_front(30);

    printDeque(d);
    //输出30 20 10 1 2 3

    //对于支持随机访问的迭代器的容器,都可以利用sort算法直接对其进行排序
    sort(d.begin(), d.end());//默认升序排序

    printDeque(d);
    //输出1 2 3 10 20 30
}

对于支持随机访问的迭代器的容器,都可以利用sort算法直接对其进行排序
 

4.stack容器

4.1基本概念

概念:stack是一种先进后出(First In Last Out,FILO)的数据结构,他只有一个开口

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

栈中进入元素为--入栈--push

栈中弹出元素为--出栈-pop

4.2stack常用接口

功能:栈容器常用的对外接口

函数原型:

//构造函数
stack<T> stk;            //默认构造函数
stack(const stack& stk>; //拷贝构造函数

//赋值操作
stack& operator= (const stack& stk);//重载等号运算符

//数据存取
push(elem);              //向栈顶添加一个元素
pop();                   //从栈顶移除一个元素
top();                   //返回栈顶元素

//大小操作
empty();                 //判断栈是否为空
size();                  //返回栈的大小

5.queue容器

5.1基本概念

概念:queue是一种先进先出的数据结构,他有两个开口

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

队列中只有队头和队尾才可以被外界使用,因此队列不允许有便利行为

队列中进元素称为--入队--push

队列中出元素称为--出队--pop

5.2queue常用接口

功能:队列容器常用的对外接口

函数原型:

//构造函数
queue<T> que;            //默认构造
queue(const queue& que); //拷贝构造

//赋值操作
queue& operator= (const queue& que);//重载等号运算符

//数据存取
push(elem);              //在队尾添加一个元素
pop();                   //从对头删除一个元素
back();                  //返回最后一个元素
front();                 //返回第一个元素

//大小操作
empty();                 //判断队列是否为空
size();                  //返回队列的大小

6.list容器

6.1基本概念

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

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

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

list的优点

-- 采用动态存储分配,不会造成内存浪费和溢出

-- 链表执行插入和删除操作十分方便,修改指针即可,不需要移动大量元素

list的缺点

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

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

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

6.2list构造函数

函数原型:

liSt<T> lst;            //默认构造
list(beg, end);         //将[beg,end)区间中的元素拷贝给本身
list(n, elem);          //将n个elem拷贝给本身
list(const list& lst);  //拷贝构造函数

6.3list赋值和交换

功能:给list容器进行赋值,以及交换list容器

函数原型:

list& operator= (const list& lst);//重载等号运算符
assign(beg, end);
assign(n,elem);
swap(lst);                        //将lst与本身的元素互换

6.4list大小操作

功能:对list容器的大小进行操作

函数原型:

size();    //返回容器中元素的个数
empty();   //判断容器是否为空
resize(num);  //同vector的resize
resize(num, elem);

6.5list插入和删除

功能:对list容器进行数据的插入和删除

函数原型:

push_back(elem);        //在容器尾部插入一个元素
pop_back();             //从容器尾部删除一个元素
push_front(elem);       //在容器头部插入一个元素
pop_front();            //从容器头部删除一个元素

insert(pos, elem);      //在pos位置插入elem元素的拷贝,返回新元素的地址
insert(pos, n, elem);   //在pos位置插入n个elen元素,无返回值
insert(pos, beg, end);  //在pos位置插入[beg,end)区间的元素,无返回值

clear();                //移除容器的所有数据

erase(beg,end);         //删除[beg,end)区间的数据,返回下一个元素的位置
erase(pos);             //删除pos位置的元素,返回下一个元素的位置
remove(elem);           //删除容器中所有值与elem值匹配的元素

6.6list数据存取

功能:对list容器中数据进行存取

函数原型:

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

list并不支持 [ ] 和 at 的方式访问,且list的迭代器不支持随机访问,只支持前移和后移,属于双向迭代器。

6.7list反转和排序

功能:将容器中的元素反转,以及将容器中的数据进行排序

函数原型:

reverse();    //反转链表
sort();       //链表排序

示例:

bool mycompareInt(int n1, int n2) {
    return n1 > n2;
}

//list反转和排序
void test10() {
    list<int> l;
    l.push_back(1);
    l.push_back(3);
    l.push_back(2);
    l.push_back(5);
    l.push_back(4);

    print_list_int(l);
    //输出1 3 2 5 4

    //所有不支持随机访问迭代器的容器,不可以使用标准算法
    //不支持随机访问迭代器的容器,内部会提供一些算法
    l.reverse();//反转链表
    print_list_int(l);
    //输出4 5 2 3 1

    l.sort();//排序链表,默认排序 从小到大
    print_list_int(l);
    //输出1 2 3 4 5 

    l.sort(mycompareInt);//从大到小
    print_list_int(l);
    //输出5 4 3 2 1 
}

    所有不支持随机访问迭代器的容器,不可以使用标准算法
    不支持随机访问迭代器的容器,内部会提供一些算法

7.set/multiset容器

7.1基本概念

简介:所有元素会在插入时自动被排序

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

set与multiset区别:

--set不允许有重复元素

--multiset允许有重复元素

7.2set构造和赋值

功能:创建set容器以及赋值

函数原型:

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

//赋值
set& operator=(const set& s);//重载等号运算符

7.3set大小和交换

功能:统计set容器大小及交换set容器

函数原型:

size();    //返回容器中元素个数
empty();   //判断容器是否为空
swap(st);  //交换两个集合容器

7.4set插入和删除

功能:set容器进行插入数据和删除数据

函数原型:

insert(elem);    //在容器插入元素
clear();         //清空容器
erase(pos);      //删除pos迭代器所指的元素,返回下一个元素的迭代器
erase(beg, end); //删除区间[beg,end)的所有元素,返回下一个元素的迭代器
erase(elem);     //删除容器中值为elem的元素

7.5set查找和统计

功能:对set容器进行查找元素以及统计元素

函数原型:

find(key);    //查找key是否存在,若存在,返回该元素的迭代器,若不存在,返回set.end();
count(key);   //统计key的元素个数

7.6set和multiset区别

区别:

-- set不可以插入重复数据,而multiset可以

-- set插入数据的同时会返回插入结果,表示是否插入成功

-- multiset不会检测数据,因此可以插入重复数据

7.7pair对组创建

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

创建方式:

//1
pair<type1, type2> p (value1, value2);

//2
pair<type1, type2> p = make_pair(value1, value2);

要想访问对组中的数据,可以直接

对象名.first访问第一个元素

对象名.second访问第二个元素

7.8内置数据类型指定排序规则

目标:set容器默认排序规则为从小到大,掌握如何改变排序规则

技术点:利用仿函数,可以改变排序规则

示例:设置set从大到小排序

//仿函数int从大到小
class mycompare1 {
public:
    bool operator() (int n1, int n2)const {
        return n1 > n2;
    }
};
//set容器内置数据类型指定排序规则
void test11() {
    set<int> s1;
    s1.insert(4);
    s1.insert(2);
    s1.insert(1);
    s1.insert(5);
    s1.insert(3);

    for (set<int>::iterator it = s1.begin(); it != s1.end(); it++) {
        cout << *it << ' ';
    }
    cout << endl;
    //输出1 2 3 4 5 

    set<int,mycompare1> s2;
    s2.insert(4);
    s2.insert(2);
    s2.insert(1);
    s2.insert(5);
    s2.insert(3);

    for (set<int,mycompare1>::iterator it = s2.begin(); it != s2.end(); it++) {
        cout << *it << ' ';
    }
    cout << endl;
    //输出5 4 3 2 1
}

7.9自定义数据类型指定排序规则

示例:

class Person {
public:
    Person(string n, int a) {
        this->name = n;
        this->age = a;
}
    string name;
    int age;
};

class mycompare2 {
public:
    bool operator() (const Person& p1, const Person& p2)const {
        return p1.age > p2.age;
    }
};

//set容器自定义数据类型指定排序规则
void test12() {
    set<Person,mycompare2> s1;
    Person p1("张三", 18);
    Person p2("李四", 19);
    Person p3("王五", 20);
    
    s1.insert(p1);
    s1.insert(p2);
    s1.insert(p3);


    for (set<Person, mycompare2>::iterator it = s1.begin(); it != s1.end(); it++) {
        cout << (*it).name << (*it).age << ' ';
        cout << endl;
    }
    cout << endl;
        //输出   "王五", 20
        //输出   "李四", 19
        //输出   "张三", 18
}

8.map/multimap容器

8.1基本概念

简介:

-- map中所有元素都是pair

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

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

本质:

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

优点:

-- 可以根据key值快速找到value值

map与multimap区别为map不允许容器中有重复key值元素,二multimap允许

8.2map构造和赋值

功能:对map容器进行构造和赋值操作

函数原型:

map<T1, T2> mp;        //默认构造
map(const map& mp);    //拷贝构造

示例:

void test13() {
    map<int, int> m1;

    //插入数据
    m1.insert(make_pair(3, 30));//利用make_pair插入
    m1.insert(make_pair(4, 40));
    m1.insert(pair<int, int>(1, 10));//创建匿名对组插入
    m1.insert(pair<int, int>(2, 20));


    for (map<int, int>::iterator it = m1.begin(); it != m1.end(); it++) {
        cout << "key: " << it->first << "  value: " << it->second << endl;
    }
    //输出 key: 1  value: 10
    //输出 key: 2  value : 20
    //输出 key : 3  value : 30
    //输出 key : 4  value : 40
}

注意:map中所有元素都是成对出现,插入数据时需要使用对组

8.3map大小和交换

功能:统计map容器大小以及交换map容器

函数原型:

size();    //返回容器中元素的数目
empty();   //判断容器是否为空
swap(mp);  //交换两个map容器

8.4map插入和删除

功能:map容器进行插入数据和删除数据

函数原型:

insert(elem);   //插入元素,看下图示例
clear();        //清空容器
erase(pos);     //删除pos迭代器所指的元素,并返回下一个元素的迭代器
erase(key);     //删除容器中 键值为key 的元素

示例:

//map插入和删除
void test14() {
    map<int, int> m1;
    
    //插入数据
    // 1
    m1.insert(pair<int, int>(1, 10));

    // 2
    m1.insert(make_pair(2, 20));
    
    // 3
    m1.insert(map<int, int>::value_type(3, 30));
    
    // 4
    m1[4] = 40;
   // [ ]不建议用来插入,可以用来利用key访问value,如 cout << m1[3]; 输出30
   //若利用 [ ]来访问不存在的key,会自动插入(key, 0) ,如 cout << m1[44]; 输出0

    for (map<int, int>::iterator it = m1.begin(); it != m1.end(); it++) {
        cout << "key: " << it->first << "  value: " << it->second << endl;
    }
    //输出 key: 1  value: 10
    //输出 key: 2  value: 20
    //输出 key: 3  value: 30
    //输出 key: 4  value: 40

    //删除
    m1.erase(2);//根据key删除元素

    for (map<int, int>::iterator it = m1.begin(); it != m1.end(); it++) {
        cout << "key: " << it->first << "  value: " << it->second << endl;
    }
    //输出 key: 1  value: 10
    //输出 key: 3  value: 30
    //输出 key: 4  value: 40
}

8.5map查找和统计

功能:对map容器进行查找元素以及统计元素

函数原型:

find(key);    //查找key是否存在,若存在,返回该键的元素的迭代器,若不存在,返回map.end();
count(key);   //统计key的元素个数

示例:

void test15() {
    map<int, int> m1;

    //插入数据
    m1.insert(make_pair(1, 10));
    m1.insert(make_pair(2, 20));
    m1.insert(make_pair(3, 30));

    map<int, int>::iterator pos = m1.find(2);
    if (pos != m1.end()) {
        cout << "已找到元素" << endl;
        cout << "key: " << pos->first << " value: " << pos->second << endl;
    }
    else {
        cout << "未找到元素" << endl;
    }
    //输出 已找到元素
    //输出 key: 2 value: 20

    pos = m1.find(111);
    if (pos != m1.end()) {
        cout << "已找到元素" << endl;
        cout << "key: " << pos->first << " value: " << pos->second << endl;
    }
    else {
        cout << "未找到元素" << endl;
    }
    //输出 未找到元素

}

注意:find返回的是迭代器

8.6map排序

技术点:利用仿函数,改变排序规则

示例:

//仿函数int从大到小
class mycompare1 {
public:
    bool operator() (int n1, int n2)const {
        return n1 > n2;
    }
};

//map改变排序规则
void test16() {
    //利用仿函数改变排序规则
    map<int, int, mycompare1> m1;

    //插入数据
    m1.insert(make_pair(1, 10));
    m1.insert(make_pair(2, 20));
    m1.insert(make_pair(3, 30));

    for (map<int, int>::iterator it = m1.begin(); it != m1.end(); it++) {
        cout << "key: " << it->first << "  value: " << it->second << endl;
    }
    //输出 key: 3  value: 30
    //输出 key: 2  value: 20
    //输出 key: 1  value: 10

}

三.函数对象(仿函数)

1.函数对象

1.1函数对象概念

概念:

-- 重载函数调用操作符的类,其对象常称为函数对象

-- 函数对象使用重载的()时,行为类似函数调用,也叫仿函数

本质:

函数对象(仿函数)是一个类,不是一个函数

1.2函数对象使用

特点:

-- 函数对象在使用时,可以像普通函数那样调用,可以有参数,可以有返回值

-- 函数对象超出普通函数的概念,函数对象可以有自己的状态

-- 函数对象可以作为参数传递

//函数对象(仿函数)调用
class myPrint {
public:
    void operator() (string text) {
        cout << text << endl;
    }
};
void test18() {

    myPrint m1;
    
    m1("hello world");
    //输出hello world
}

2.谓词

2.1谓词概念

概念:

-- 返回bool类型的仿函数称为谓词

-- 如果operator()接受一个参数,叫做一元谓词

-- 如果operator()接受两个参数,叫做二元谓词

2.2一元谓词

示例:

//一元谓词
//大于5为真
class GreaterFive {
public:
    bool operator() (int n) {
        return n > 5;
    }
};

void test19() {
    vector<int> v1;
    v1.push_back(4);
    v1.push_back(5);
    v1.push_back(6);

    vector<int>::iterator it;

    //GreaterFive()为匿名的函数对象
    it = find_if(v1.begin(), v1.end(), GreaterFive());

    cout << *it << endl;
    //输出6
}

提示:在谓词类里加一个有参构造,就可以随意控制大于或小于几的条件,就不用重复写谓词

2.3二元谓词

示例:

//仿函数int从大到小
class mycompare1 {
public:
    bool operator() (int n1, int n2)const {
        return n1 > n2;
    }
};

//二元谓词
//从大到小排序
void test20() {
    vector<int> v1;
    v1.push_back(4);
    v1.push_back(3);
    v1.push_back(2);
    v1.push_back(1);
    v1.push_back(5);

    //sort默认从小到大
    sort(v1.begin(), v1.end());

    for (vector<int>::iterator it = v1.begin(); it != v1.end(); it++) {
        cout << *it << ' ';
    }
    cout << endl;
    //输出1 2 3 4 5 

    //mycompare1()为匿名函数对象
    sort(v1.begin(), v1.end(), mycompare1());

    for (vector<int>::iterator it = v1.begin(); it != v1.end(); it++) {
        cout << *it << ' ';
    }
    cout << endl;
    //输出5 4 3 2 1

}

3.内建函数对象

3.1内建函数对象意义

概念:

-- STL内建了一些函数对象

分类:

-- 算术仿函数

-- 关系仿函数

-- 逻辑仿函数

用法:

-- 这些仿函数所产生的对象,用法和一般函数完全相同

-- 使用内建函数对象,需要引入头文件<functional>

3.2算术仿函数

功能:实现四则运算,其中negate是一元运算,其他都是二元运算

仿函数原型:

template<class T> T plus<T>        //加法仿函数
template<class T> T minus<T>       //减法仿函数
template<class T> T multiplies<T>  //乘法仿函数
template<class T> T divides<T>     //除法仿函数
template<class T> T modulus<T>     //取模仿函数
template<class T> T negate<T>      //取 相反数 仿函数

示例:

//算术仿函数
void test21() {
    //一元仿函数,取反
    negate<int> n;
    cout << n(100) << endl;
    //输出-100

    //二元仿函数,相加
    plus<int> p;
    cout << p(100, 200) << endl;
    //输出300

}

3.3关系仿函数

功能:实现关系对比

仿函数原型:

template<class T> bool equal_to<T>;        //等于
template<class T> bool not_equal<T>;       //不等于
template<class T> bool greater<T>;         //大于
template<class T> bool greater_equal<T>;   //大于或等于
template<class T> bool less<T>;            //小于
template<class T> bool less_equal<T>;      //小于或等于

示例:

//关系仿函数
void test22() {
    vector<int> v;
    v.push_back(1);
    v.push_back(2);
    v.push_back(3);
    v.push_back(4);
    v.push_back(5);

    //传入匿名对象
    sort(v.begin(), v.end(), greater<int>());
    //或者    greater<int> g;
    //           sort(v.begin(), v.end(), g);

    for (vector<int>::iterator it = v.begin(); it != v.end(); it++) {
        cout << *it << ' ';
    }
    cout << endl;
    //输出5 4 3 2 1

    //传入类型
    set<int, greater<int>> s;
    s.insert(1);
    s.insert(2);
    s.insert(3);
    s.insert(4);
    s.insert(5);
    
    for (set<int>::iterator it = s.begin(); it != s.end(); it++) {
        cout << *it << ' ';
    }
    cout << endl;
    //输出5 4 3 2 1 

}

3.4逻辑仿函数

功能:实现逻辑运算

函数原型:

template<class T> bool logical_and<T>;    //逻辑与
template<class T> bool logical_or<T>;     //逻辑或
template<class T> bool logical_not<T>;    //逻辑非

四.常用算法

概述:

-- 算法主要是由头文件<algorithm> <functional> <numeric>组成

-- <algorithm>是所有STL文件中最大的一个,范围涉及到比较、交换、查找、遍历操作、复制、修改等等

-- <numerical>体积很小,只包括几个在序列上面进行简单数学运算的模板函数

-- <functional>定义了一些模板类,用以声明函数对象

1.常用遍历算法

算法简介:

for_each    //遍历容器
transform   //搬运容器到另一个容器中

1.1for_each

功能:实现遍历容器

函数原型;

for_each(iterator beg, iterator end, _func);
//遍历算法 遍历容器元素
//beg开始迭代器
//end结束迭代器
//_func 函数或函数对象

示例:

//常用遍历算法 for_each
void print01(int v) {
    cout << v << ' ';
}

class print02 {
public:
    void operator()(int v) {
        cout << v << ' ';
    }
};

void test23() {
    vector<int> v1;
    v1.push_back(1);
    v1.push_back(2);
    v1.push_back(3);
    v1.push_back(4);
    v1.push_back(5);

    //利用普通函数
    for_each(v1.begin(), v1.end(), print01);
    cout << endl;
    //输出1 2 3 4 5 

    //利用仿函数
    for_each(v1.begin(), v1.end(), print02());
    cout << endl;
    //输出1 2 3 4 5 

}

1.2transform

功能:搬运容器到另一个容器中

函数原型:

transform(iterator beg1, iterator end1, iterator beg2, func_); 
//beg1 源容器开始迭代器
//end1 源容器结束迭代器
//beg2 目标容器开始迭代器
//func_ 函数或函数对象

示例:

//常用遍历算法 transform
class Transform1{
public:
    int operator() (int v) {
        return v + 100;
    }
};

class print02 {
public:
    void operator()(int v) {
        cout << v << ' ';
    }
};

void test24() {
    vector<int> v1; //源容器

    v1.push_back(1);
    v1.push_back(2);
    v1.push_back(3);
    v1.push_back(4);
    v1.push_back(5);

    vector<int>vTarget; //目标容器
    vTarget.resize(v1.size());//目标容器需要提前开辟空间

    transform(v1.begin(), v1.end(), vTarget.begin(), Transform1());

    for_each(v1.begin(), v1.end(), print02());
    //输出1 2 3 4 5 即源容器不变

    for_each(vTarget.begin(), vTarget.end(), print02());
    //输出101 102 103 104 105

}

注意:目标容器需要提前开辟空间,且源容器内元素不变

2.常用查找算法

算法简介:

find            //查找元素
find_if         //按条件查找元素
adjacent_find   //查找相邻重复元素
binary_search   //二分查找法
count           //统计元素个数
count_if        //按条件统计元素个数

2.1find

功能:查找指定元素,找到返回指定元素的迭代器,找不到返回结束迭代器end()

函数原型:

find(iterator beg, iterator end, value);
//按值查找元素,找到返回指定位置迭代器,找不到返回结束迭代器
//beg 开始迭代器
//end 结束迭代器
//value 查找的元素

示例:

//常用查找算法 find
class Person {
public:
    Person(string n, int a) {
        this->name = n;
        this->age = a;
}

    bool operator== (const Person& p) {
        if (this->name == p.name && this->age == p.age) {
            return true;
        }
        else return false;
    }

    string name;
    int age;
};

void test25() {
    //1.查找内置数据类型

    vector<int> v1; 
    v1.push_back(1);
    v1.push_back(2);
    v1.push_back(3);
    v1.push_back(4);
    v1.push_back(5);

    //查找 v1 中是否有5这个元素
    vector<int>::iterator it1;
    it1 = find(v1.begin(), v1.end(), 5);

    if (it1 != v1.end()) {
        cout << "找到5了"<<endl;
    }
    else {
        cout<<"没有找到5"<<endl;
    }
    //输出找到5了



    //2.查找自定义数据类型

    vector<Person> v2;
    v2.push_back(Person("张三", 18)); //Person("张三", 18)为匿名对象
    v2.push_back(Person("李四", 19));
    v2.push_back(Person("王五", 20));

    vector<Person>::iterator it2;
    it2 = find(v2.begin(), v2.end(), Person("张三", 18));

    if (it2 != v2.end()) {
        cout << "找到该人员了" << endl;
        cout << "姓名:" << (*it2).name << " 年龄:" << (*it2).age << endl;
    }
    else {
        cout << "没有找到该人员"<<endl;
    }
    //输出 找到该人员了
    //输出 姓名:张三 年龄:18

}

注意:查找自定义数据类型,要重载 == 运算符

2.2find_if

功能:按条件查找元素

函数原型:

find_if(iterator beg, iterator end, _Pred);
//按值查找元素,找到返回指定位置迭代器,找不到返回结束迭代器
//beg 开始迭代器
//end 结束迭代器
//_Pred 函数或谓词(返回bool类型的仿函数)

2.3adjacent_find

功能:查找相邻重复元素

函数原型:

adjacent_find(iterator beg, iterator end);
//查找相邻重复元素,找到返回相邻元素的第一个位置的迭代器,找不到返回结束迭代器
//beg 开始迭代器
//end 结束迭代器

2.4binary_search

功能:在有序序列中查找指定元素是否存在

函数原型:

binary_search(iterator beg, iterator end, value);
//按值查找元素,找到返回true,找不到返回false
//beg 开始迭代器
//end 结束迭代器
//value 查找的元素

2.5count

功能:统计元素个数

函数原型:

count(iterator beg, iterator end, value);
//统计元素出现的个数
//beg 开始迭代器
//end 结束迭代器
//value 统计的元素

注意:统计自定义数据类型,要重载 == 运算符

2.6count_if

功能:按条件统计元素个数

函数原型:

count_if(iterator beg, iterator end, _Pred);
//按条件统计元素出现的次数
//beg 开始迭代器
//end 结束迭代器
//_Pred 函数或谓词(返回bool类型的仿函数)

3.常用排序算法

算法简介:

sort            //对容器内元素进行排序
random_shuffle  //洗牌 指定范围内的元素随机调整次序
merge           //容器元素合并,并存储到另一个容器中
reverse         //反转指定范围的元素

3.1sort

功能:对容器内元素进行排序

函数原型:

sort(iterator beg, iterator end, _Pred);
//beg 开始迭代器
//end 结束迭代器
//_Pred 函数或谓词(返回bool类型的仿函数)默认从小到大

示例:

/常用排序算法
class print02 {
public:
    void operator()(int v) {
        cout << v << ' ';
    }
};

void test26() {
    vector<int> v1;
    v1.push_back(3);
    v1.push_back(1);
    v1.push_back(2);
    v1.push_back(4);
    v1.push_back(5);

    //greater<int> 为内建函数对象
    sort(v1.begin(), v1.end(), greater<int>());

    for_each(v1.begin(), v1.end(), print02());
    cout << endl;
    //输出5 4 3 2 1

}

3.2random_shuffle

功能:洗牌 指定范围内的元素随机调整次序

函数原型:

random_shuffle(iterator beg, iterator end);
//beg 开始迭代器
//end 结束迭代器

示例:

//常用排序算法
void test26() {
    //随机数种子
    srand((unsigned int)time(NULL));

    vector<int> v1;
    v1.push_back(1);
    v1.push_back(2);
    v1.push_back(3);
    v1.push_back(4);
    v1.push_back(5);

    random_shuffle(v1.begin(), v1.end());

    for_each(v1.begin(), v1.end(), print02());
    cout << endl;
    //输出随机序列
}

注意:使用时记得加随机数种子

3.3merge

功能:容器元素合并,并存储到另一个容器中(两个容器必须是有序的

函数原型:

random_shuffle(iterator beg1, iterator end1, iterator beg2, iterator end2, iterator dest);
//两个容器必须是有序的
//beg1 容器1开始迭代器
//end1 容器1结束迭代器
//beg2 容器2开始迭代器
//end2 容器2结束迭代器
//dest 目标容器开始迭代器

注意:需要提前给目标容器分配空间,大小为 (size1+size2)

3.4reverse

功能:反转指定范围的元素

函数原型:

reverse(iterator beg, iterator end);
//beg 开始迭代器
//end 结束迭代器

注意:    所有不支持随机访问迭代器的容器,不可以使用标准sort算法
               不支持随机访问迭代器的容器,内部会提供一些算法

4.常用拷贝和替换算法

算法简介:

copy        //容器内指定范围的元素拷贝到另一个容器
replace     //将容器内指定范围的旧元素修改为新元素
replace_if  //容器内指定范围满足条件的元素替换为新元素
swap        //互换两个容器的元素

4.1copy

功能:容器内指定范围的元素拷贝到另一个容器

函数原型:

copy(iterator beg1, iterator end1, iterator dest);
//两个容器必须是有序的
//beg 容器1开始迭代器
//end 容器1结束迭代器
//dest 目标容器开始迭代器

注意:需要提前给目标容器分配空间

4.2replace

功能:将容器内指定范围的旧元素修改为新元素

函数原型:

replace(iterator beg, iterator end, oldvalue, newvalue);
//beg      容器开始迭代器
//end      容器结束迭代器
//oldvalue 旧元素
//newvalue 新元素

4.3replace_if

功能:容器内指定范围满足条件的元素替换为新元素

函数原型:

replace_if(iterator beg, iterator end, _Pred, newvalue);
//beg      容器开始迭代器
//end      容器结束迭代器
//_Pred    谓词
//newvalue 新元素

4.4swap

功能:互换两个容器的元素

函数原型:

swap(contain c1, contain c2);
//两个容器必须同种类型
//c1 容器1
//c2 容器2

5.常用算术生成算法

算法简介:

accumulate    //计算容器元素累计总和
fill          //向容器中添加元素

注意:算术生成算法属于小型算法,使用时包含头文件<numeric>

5.1accumulate

功能:计算容器元素累计总和

函数原型:

accumulate(iterator beg, iterator end, value);
//beg    容器开始迭代器
//end    容器结束迭代器
//value  起始累加值,若只算该容器中的总值就将其设为0

5.2fill

功能:后期向容器中填充元素

函数原型:

fill(iterator beg, iterator end, value);
//beg    容器开始迭代器
//end    容器结束迭代器
//value  填充的值

6.常用集合算法

算法简介:

set_intersection    //求两个容器的交集
set_union           //求两个容器的并集
set_difference      //求两个容器的差集

6.1set_intersection

功能:求两个有序容器的交集

函数原型:

set_intersection(iterator beg1, iterator end1, iterator beg2, iterator end2, iterator dest);
//beg1 容器1开始迭代器
//end1 容器1结束迭代器
//beg2 容器2开始迭代器
//end2 容器2结束迭代器
//dest 目标容器开始迭代器

//返回最后一个交集元素的迭代器

注意:需要提前给目标容器分配空间为 小的size( min(v1.size(),v2.size() )

           返回最后一个交集元素的迭代器

6.2set_union

功能:求两个有序容器的并集

函数原型:

set_union(iterator beg1, iterator end1, iterator beg2, iterator end2, iterator dest);
//beg1 容器1开始迭代器
//end1 容器1结束迭代器
//beg2 容器2开始迭代器
//end2 容器2结束迭代器
//dest 目标容器开始迭代器

//返回最后一个并集元素的迭代器

注意:需要提前给目标容器分配空间为 (v1.size() + v2.size() )

           返回最后一个并集元素的迭代器

6.3set_difference

功能:求两个有序容器的差集

函数原型:

set_difference(iterator beg1, iterator end1, iterator beg2, iterator end2, iterator dest);
//beg1 容器1开始迭代器
//end1 容器1结束迭代器
//beg2 容器2开始迭代器
//end2 容器2结束迭代器
//dest 目标容器开始迭代器

//返回最后一个差集元素的迭代器

注意:需要提前给目标容器分配空间为 v1.size() (第一个参数容器的size)

           返回最后一个差集元素的迭代器

  • 21
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值