//STL六大类:
//容器: 各种数据结构(Vvector,list,deque,set,map等等)
//算法: 常用算法,如sort,find,copy,for_each.
//迭代器: 容器和算法间的联系纽带
//仿函数: 行为类似仿函数,可作为算法的某种策略。
//适配器(配接器: 修饰容器和或者仿函数迭代器接口的东西
//空间配置器: 负责空间的配置和管理。
*一、string类型
1-1声明和赋值
void string_01()
{
string s1; //声明
//下面为赋值方式
getline(cin, s1);
cout << s1 << endl;
char s2[] = "kakamolaiwe";
string s3(s2);
cout << s3 << endl;
const char *c = "nishishuis所示";
string s4(c);
cout << s4 << endl;
string s5(5, 'g');
cout << s5 << endl;
//用 [ ] 调用和赋值
cout<<s5[2]<<endl
1-2string中的功能函数
void string_02()
{
//赋值函数
string s0 = "kkskskshjs";
char c[] = "这是一个char型数组";
const char *c2 = "这是一个char*型";
string s1;
s1 = s0;
cout << s1 << endl;
string s2;
s2 = 2;
cout << s2 << endl;
s2 = c2;
cout << s2 << endl;
s2.assign(s0);
cout << s2 << endl;
s2.assign(c);
cout << s2 << endl;
s2.assign(c2);
cout << s2 << endl;
s2.assign(c2, 3);
cout << s2 << endl;
s2.assign(34, 'f');
cout << s2 << endl;
s2.assign("hello", 3);
cout << s2 << endl;
}
1-3 string字符串拼接
//string字符串拼接
void string_04()
{
string s = "卡卡";
const char *c = "molaiwei";
char c2[] = { 's','i' };
char c3[] = "shuaige";
s += c;
cout << s << endl;
s += c2;
cout << s << endl;
s += c3;
cout << s << endl;
string s1;
s1.append(s);
s1.append(c, 3, 6);
s1.append(c2, 1);
s1.append(c3);
s1.append(5, 'f');
s1.append("lox");
cout << s1 << endl;
//从左查找然后输出位置,0开始
int pos = s1.find('m');
//从右开始查找字符,输出位置。
int pos2 = s1.rfind("卡卡");
//0-3替换为kaka
//s1.replace(0, 3, "kaka");
cout << pos << pos2 << endl;
cout << s1 << endl;
//字符串比较(逐位比较ascii码值)
int bo = s1.compare(s);
cout << bo << endl;
//读取和写入如字符串中单独位置元素
cout << s1.at(4) << " " << s1[5] << endl;
s1 = "kakamolaiwei";
//插入和删除
s1.insert(3, "ka");
cout << "s1" << s1 << endl;
//0后面3个全删除了
s1.erase(0, 3);
cout << s1 << endl;
//取子串,位置2后面取4个。
string sub = s1.substr(2, 4);
cout << sub << endl;
}
**
二、vector容器
**
2-1 被调用函数外部实现
//遍历int型Vector对象函数
void printVector(vector<int> &p)
{ //利用迭代器访问
for (vector<int>::iterator it = p.begin(); it != p.end(); it += 1)
{
cout << *it << '\t';
}
cout << endl;
}
//遍历string型Vector对象
void printStrVec(vector<string>&p)
{
for (vector<string>::const_iterator it = p.begin(); it != p.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
//将两个int型vector对象拼接
void pushback1(vector<int>&v1, vector<int>&v2)
{
for (vector<int>::iterator it = v2.begin(); it != v2.end(); it++)
{
v1.push_back(*it);
cout << *it << endl;
}
}
2-2 vector使用主函数
void test05()
{
vector<int>v;
for (int i = 5; i < 16; i++)
{
v.push_back(i);
}
printVector(v);
//调用的直接是对象本身,区别于迭代器
for_each(v.begin(), v.end(), printPTR);
vector<int>v2;
for (int i = 17; i < 26; i++)
{
v2.push_back(i);
}
printVector(v2);
//v2.assign(v.begin(),v.end());
//printVector(v2);
vector<int>v3(v);
printVector(v3);
v3 = v2;
printVector(v3);
pushback1(v3, v);
printVector(v3);
v3 = { 1,2,3 };
printVector(v3); //输出1 2 3
//v3的容量(动态分配的)始终比大小大,大小指的是存放的元素个数。
cout << "v3的容量" << v3.capacity() << "v3的大小" << v3.size() << endl;
v3.resize(5);
//重新指定大小后,多余的大小用0代替,当vector插值或者复制等改变大小的操作时
//相对于静态地数组,容器(动态分配)会重新找一个内存,将之前的元素拷贝过来,然后再完成各种操作。
printVector(v3); //输出: 1 2 3 0 0
cout << "v3的容量" << v3.capacity() << "v3的大小" << v3.size() << endl;
//vector插值和删除
v3 = { 0 };
cout << "各种插入类型" << endl;
//尾插
v3.push_back(1);
v3.push_back(2);
v3.push_back(3);
//尾删
v3.pop_back();
vector<int>v4(v3);
//自定义位置插入(选哪个位置插哪个位置前面,选0,就插在首位)
v3.insert(v3.begin(), 6);
printVector(v3);
//擦除也是需要穿迭代器
vector<int>::iterator a = v3.begin()++;
vector<int>::iterator b = v3.begin() + 2;
v3.erase(v3.begin(), --v3.end());
cout << "是否完全擦除" << endl;
printVector(v3);
v4 = { 3,2,6,1,2,5,7,2,5,7 };
printVector(v4); //打印:3,4,6,1,2,5,7,2,5,7
//remove返回的是新的 end() ,将容器里面值为为2的元素放在容器后面(也即是原来的 end()后面)
//因为不是Vector的函数,所以不会改变其大小和容量,原begin()和end()指向位置不变,但是begin()和新的end()之间移除2的位置由后一元素补充
//但是新end()和旧end()之间仍然指向的是之前的元素,做的一种逻辑上的删除。
auto p = remove(v4.begin(), v4.end(), 2); //将容器中所有的不为2的元素前移,返回新的end()迭代器,指向后面全部2的第一个位置。
printVector(v4); //打印:3,4,6,1,5,7,5,7,5,7
//用erase或者resize擦除所有2;
//v4.erase(p, v4.end());
v4.resize(8);
printVector(v4); //打印:3,4,6,1,5,7,5,7,
v4.clear();//置空V4
printVector(v4);
cout << "v4的容量" << v4.capacity() << "v4的大小" << v4.size() << endl;
//元素访问
vector<string> str = { "ka","ka","molaiwei" };
string str2 = "kakamolaiwei";
//用at访问
cout << str.at(1) << endl;
cout << str2.at(1) << endl;
//用back和front获取尾首元素
cout << "首元素是:" << str.front() << "尾元素是:" << str.back() << endl;
cout << "首元素是:" << str2.front() << "尾元素是:" << str2.back() << endl;
//用迭代器访问
//用[ ]访问
cout << "用[ ]访问" << str[2] << endl;
cout << str2[6] << endl;
//同类型容器元素互换 利用swap()函数,容量大小也互换
vector<string> str3 = { "临时", "参数" };
cout << "交换前str :"; printStrVec(str);
cout << "交换前str3 "; printStrVec(str3);
cout << "交换前str容量大小:" << str.capacity() << " " << str.size() << endl;
cout << "交换前str3容量大小:" << str3.capacity() << " " << str3.size() << endl;
str3.swap(str);
cout << "交换后str :"; printStrVec(str);
cout << "交换后str3 "; printStrVec(str3);
cout << "交换后str容量大小:" << str.capacity() << " " << str.size() << endl;
cout << "交换后str3容量大小:" << str3.capacity() << " " << str3.size() << endl;
//利用swap()和其本身同名匿名对象(用完销毁)收缩空间。
vector<string>(str).swap(str);
cout << "收缩后str容量大小:" << str.capacity() << " " << str.size() << endl;
//利用reserve预留空间,让容器在插值时不用一直因为空间不足重新开辟新空间。
vector<string> str5;
str5.reserve(1000); //预留的是size.
}
三、deque容器
3-1 被调函数外部实现
//遍历int型deque对象
void printDeqInt(deque<int>&d1)
{
for (deque<int>::const_iterator it = d1.begin(); it != d1.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
3-2 主函数
void deque_test()
{
//deque双端队列容器前后端插入比Vector效率高,deque将前后都在缓冲区预留有空间
//不是像Vector插入多于容量时要重新申请空间,而且在前端插入元素也不像vector一樣需要把後面所有的元素往後移。
//但是访问的时候没有vector快,因为中控区里面前后端缓冲区和中间队列不在同一个内存地址,
//只是将他们的地址存在一起,实现逻辑上的连续,deque沒有容量限制,所以獲取不到容量,只能得到大小size
//1、构造函数
deque<int>d1{ 0,1,2,3 };
d1[0] = 2;
printDeqInt(d1); //打印2 1 2 3
//插入 前 後 指定位置
d1.push_front(-1);
d1.push_back(4);
d1.insert(d1.begin() + 2, 1, 6); //位置3插入 1 個 6.
printDeqInt(d1); //打印-1 2 6 1 2 3 4
//刪除 前 後 指定位置
d1.pop_back();
d1.pop_front();
d1.erase(d1.begin() + 2, d1.begin() + 4);//擦除3,4位置
printDeqInt(d1); //打印 2 6 3
//用assign賦值
deque<int> d2;
d2.assign(d1.begin(), d1.end());
printDeqInt(d2); //打印 2 6 3
//用resize重新指定大小,默認填充0,指定填充666
d1.resize(100, 666);
printDeqInt(d1); //打印 2 6 3 666 666 666...
//数据存取 back() front() at() .[ index]
cout << d1.back() << " " << d1.front() << " " << d1.at(3) << " " << d1[4] << endl;
//利用sort()函数对指定区域内排序(vector也可使用sort)
deque<char> ch = { '1','a','Z','?' };
cout << (int)ch[2] << endl;
sort(ch.begin(), ch.end()); //从小到大排序
cout << ch[0] << " " << ch[1] << " " << ch[2] << " " << ch[3] << endl;
}
四、stcak栈容器
//stack栈容器(只能入栈和出栈) 栈底不能操作,栈顶进出,先进后出
//只有栈顶元素能被访问,所以不能遍历(可以判断空empty和size)
void stack_test()
{
//常用接口
stack<int> sk;
sk.push(1);
sk.push(12);
sk.push(34);
//查看每个元素
while (!sk.empty()) //不为空
{
cout << sk.top() << " "; //top为栈顶元素 打印: 34 12 1
sk.pop(); //出栈
cout << sk.size();// 2 1 0
}
cout << endl;
}
五、deque容器
//队列容器queue ,头进 尾出,先进先出,只有队头和队尾能被访问,不允许遍历。
//接口 pop 出队 push 入队(从尾部back入队); front 队头 back 队尾;
void test08()
{
queue<int> qe;
for (int i = 0; i < 10; i += 2)
{
qe.push(i);
cout << qe.back() << " "; //尾部在增加新元素
}
if (!qe.empty()) //有可以判断是否为空和大小
{
cout << qe.size();
}
}
## 六、List链表
//普通链表list 三要素: 节点地址指针header,数据域(data),尾指针next(尾指针指向下一个元素节点地址)
//链表最后元素尾指针指向NULL,可以对任意位置插入删除,但是遍历速度没有数组快(寻址作用),占用空间较大
//相对于普通的链表,STL中的list容器是双向循环的链表,利用prev指针指向前一个表头。
//迭代器只支持前移和后移,因为其不是一段连续的空间
```cpp
在这里插入代码片
6-1 被调函数外部实现
//int型list对象遍历
void printListInt(list<int> &p)
{
for (list<int>::iterator it = p.begin(); it != p.end(); it++)
{
cout << *it << '\t';
}
cout << endl;
}
6-2 list使用
void test09()
{
list<int> lis;
lis.push_back(1);
lis.push_back(34);
lis.push_back(56);
lis.push_back(84);
lis.push_back(34);
printListInt(lis);
list<int> ls2;
ls2.swap(lis);
printListInt(lis);
//函数接口 跟deque类似;尾插,头插,随机插入,擦除erase,清除所有clear()
//说到底链表容器仍然是一个容器,只是存储的方式跟其他有区别。
//list的 remove 成员函数
ls2.remove(34);//移除所有值为34的元素。
printListInt(ls2); //打印:1 56 84
lis = ls2;
printListInt(lis);
//list中的数据存取不能用[ ] 和 .at()访问,因为其不是一段连续线性存储空间
//用迭代器++/--访问
list<int>::iterator it = lis.end();
it--;//执行完后位置为3 不能用 it+=1或者it+=2 ,只能逐个移动迭代器指针
it--;//执行完后位置为2
it--;//执行完后位置为1即 lis.begin()
cout << *it << endl; //打印 1 (第一个元素)
cout << *++it << endl; //打印 56 (第二个元素)
cout << "打印首尾元素" << endl;
cout << lis.front() << endl;
cout << lis.back() << endl;
//list 反转和排序
//notice: 所有不支持随机访问迭代器的容器都不支持全局算法<algorithm>
lis.push_back(23); lis.push_back(85); lis.push_back(7);
cout << "从小到大排序: " << endl;
lis.sort(); //不可以用全局sort,只能用list重载的成员函数.sort()
printListInt(lis);
cout << "从小到大排序: " << endl;
lis.sort(compare__kaka); //默认从小到大排列,如果需要从大到小需要加入自己写的带bool返回值规则的函数名
printListInt(lis);
lis.reverse();//反转
cout << "反转函数" << endl;
printListInt(lis);
}
七、队列模式pair
void pair_test()
{
//构造函数默认参数构造和make_pair
pair<string, int> kaka("卡卡", 25);
pair<string, int> kaka2 = make_pair("卡卡2", 25);
//利用 .first和 .second访问
cout << "第一个对组姓名:" << kaka.first << endl
<< "第二个对组的年龄:" << kaka2.second << endl;
}
八、set/multiset map/multimap
8-1 被调函数外部实现
bool compare__kaka(int &a, int &a2)
{
return a > a2;
}
//遍历int型set容器
void printSetInt(set<int>&s)
{
for (set<int>::iterator it = s.begin(); it != s.end(); it++)
{
cout << *it << endl;
}
}
//指定set容器排序规则
class set_compare
{
public:
bool operator()(int v1, int v2)
{
return v1 > v2;
}
};
//map/multimap容器遍历操作函数
void printMapSTR(map<int, string>&mp)
{
for (map<int, string>::iterator it = mp.begin(); it != mp.end(); it++)
{
cout << (*it).first << " ";
}
cout << endl;
}
void printMultimapSTR(multimap<string, string>&mp2)
{
for (multimap<string, string>::iterator it = mp2.begin(); it != mp2.end(); it++)
{
cout << (*it).first << " ";
}
cout << endl;
}
class map_compare
{
public:
bool operator()(int a1,int a2)
{
return a1 > a2;
}
};
8-2 set/multiset容器
//set/multiset 容器:插入自动排序(二叉树),set不允许插入同一个值,multiset可以
void test10()
{
//支持 swap,size empty erase /重载新增erase( elem)
//不支持resize,和使用at和[ ]访问
set<int> s1;
s1.insert(10); //不可以用push_back;
s1.insert(110);
s1.insert(150);
s1.insert(56);
printSetInt(s1); //打印 10 56 110 150
//查找 find() 找到返回元素位置迭代器,未找到返回.end()
cout << "找到元素: " << *s1.find(56) << endl; //打印 56
//利用仿函数改变set排序规则(默认从小到大)
set<int, set_compare> s2;
s2.insert(10); //不可以用push_back;
s2.insert(110);
s2.insert(150);
s2.insert(56);
cout << "遍历s2: ";
for (set<int, set_compare>::iterator it = s2.begin(); it != s2.end(); it++)
{
cout << *it << " ";
}
cout << endl;//打印 150 110 56 10
}
8-3 map/multimap 容器
void map_test()
{
//map的 key 值不允许重复,multimap 允许key值重复,并且插入值时会根据第一个即first键值来排序。
map<int, string> mp;
mp.insert(pair<int, string>(1, "卡卡")); //利用对组pair创建匿名数组插入到map容器
mp.insert(pair<int, string>(6, "卡卡2")); //利用对组pair创建匿名数组插入到map容器
mp.insert(pair<int, string>(2, "卡卡3")); //利用对组pair创建匿名数组插入到map容器
mp.insert(pair<int, string>(5, "卡卡4")); //利用对组pair创建匿名数组插入到map容器
//遍历key值
cout << "遍历mp key值: ";
printMapSTR(mp);
multimap<string, string> mp2;
mp2.insert(pair<string, string>("momo", "卡卡")); //利用对组pair创建匿名数组插入到map容器
mp2.insert(pair<string, string>("momo", "卡卡2"));
mp2.insert(pair<string, string>("啦omo", "卡卡"));
mp2.insert(make_pair("啦omo", "卡卡")); //利用对组pair创建匿名数组插入到map容器
cout << "遍历mp2key值: ";
printMultimapSTR(mp2);
//map的大小和交换: 可以用swap 和 empty size 不赘诉
//插入 insert
mp2.insert(make_pair("kaak", "卡卡3")); //利用make_pair 插入
mp2.insert(map<string, string>::value_type("zailai", "卡卡4"));
//mp2["momoss"] = "value"; //用 map[ 键值 ] = Value 进行赋值(不建议用作插值,用于访问比较合适)
printMultimapSTR(mp2);
//查找操作 find 找到返回迭代器,否则返回尾 .end( ), count(key) 计数
cout <<"有多少个momo:"<< mp2.count("momo") << endl; //输出mp2中有多少个 momo
cout << "找到键值为 momo 的 value:" << (*mp2.find("momo")).second << endl; //利用键值查找
//删除操作 erase() clear()
mp2.erase(++mp2.begin());//按迭代器删除
mp2.erase("啦omo"); //按照键值删除
printMultimapSTR(mp2);
mp2.erase(++mp2.begin(), --mp2.end());//按区间删除
printMultimapSTR(mp2);
//修改map排序方式(默认从小到大)
map<int, string,map_compare> mp3; //利用类 map_compare 中的仿函数
mp3.insert(make_pair(4,"aaa"));
mp3.insert(make_pair(1, "ssd"));
mp3.insert(make_pair(2, "sd"));
mp3.insert(make_pair(5, "sdf"));
}