一 forward_list
1.基本概念
forward_list 始于c++11,是一个single linked list管理元素
头文件 #include <forward_list>
namespace std{
template<typename T,typename Allocator = allocator>
class forward_list;
};
元素类型:可以为任意类型的T,默认的内存类型是allocator
2.forward_list的能力
forward_list是一个行为受限制的list,不能走回头路,凡是list没有的功能,forward_list都不提供
优点:内存用量少,行动略迅速
设计目标:和自己写的c-style linked list比较,没有任何空间和时间上的额外开销
如果任何方法和这两个要求相违背,就应该放弃该方法(API)
3.for_ward的约束
1.只提供前向迭代器,而不是双向迭代器,不支持反向迭代器
2.不提供成员函数size()--->不允许空间时间的浪费
因为size()被调用,要么直接计算其大小,要么需要提供一个额外的数据栏记录其大小
只要某个有能力改变其大小的函数被调用,这个数据栏都要去更新检查
-->解决方案:1.自行追踪 2.使用list
3.forward_list没有指向最末元素的anchor(锚点),所以不提供给处理最末元素的成员函数
比如:push_back(),pop_back()都不提供
-->解决方案:1.提供特殊版本(xx_after),(before_xx)
4.注意事项
1.forward_list不支持随机访问,如果想要访问第n个元素,必须遵循link所形成的串链“航行”前n个元素,因此速度相当满。
2.在任意位置安插和移除,因为没有任何元素需要搬移,只有若干个pointer需要被涂改
3.在这个里面提供特殊成员函数,是一般算法的快速版本。
#include <iostream>
#include <forward_list>
#include <string>
using namespace std;
int main(void)
{
forward_list<int> f1 = { 1,2,3,4,5,6 };
f1.emplace_front(7);
f1.emplace_after(f1.before_begin(), 88);
for (auto &l : f1)
{
cout << l << " ";
}
cout << endl;
f1.insert_after(f1.before_begin(), {11,22,33});
for (auto &l : f1)
{
cout << l << " ";
}
cout << endl;
forward_list<int> l1 = { 1,2,3,4,5 };
forward_list<int> l2 = { 97,98,99 };
auto pos1 = l1.cbefore_begin();
for (auto t1 = l1.begin(); t1 != l1.end(); ++t1,++pos1)
{
if (*t1 == 3)
{
break;
}
}
auto pos2 = l2.cbefore_begin();
for (auto t2 = l2.begin(); t2 != l2.end(); ++t2, ++pos2)
{
if (*t2 == 99)
{
break;
}
}
l2.splice_after(pos2,l1,pos1);
for (auto &l : l2)
{
cout << l << " ";
}
cout << endl;
for (auto &l : l1)
{
cout << l << " ";
}
cout << endl;
return 0;
}
练习 for_ward_list运用实例
forward_list<int> list1 = {1,2,3,4};
forward_list<int> list2 = {77,88,99};
#include <iostream>
#include <forward_list>
#include <string>
#include <algorithm>
#include <iterator>
using namespace std;
void printList(const string &s, const forward_list<int> &l1, const forward_list<int> &l2)
{
cout << s << endl;
cout << "list1:" << endl;
copy(l1.begin(),l1.end(), ostream_iterator<int>(cout, " "));
cout << endl;
cout << "list2:" << endl;
copy(l2.begin(), l2.end(), ostream_iterator<int>(cout, " "));
cout << endl;
}
int main(void)
{
forward_list<int> list1 = { 1,2,3,4 };
forward_list<int> list2 = { 77,88,99 };
printList("init list1 list2:",list1,list2);
list2.emplace_after(list2.cbefore_begin(), 99);
list2.emplace_front(10);
list2.insert_after(list2.before_begin(), {10,11,12,13});
printList("插入六个元素:", list1, list2);
list1.insert_after(list1.before_begin(),list2.begin(),list2.end());
printList("在list1的开头插入list2中所有的元素:", list1, list2);
list2.erase_after(list2.begin());
list2.erase_after(find(list2.begin(), list2.end(), 99), list2.end());
printList("删除list2中第二个元素和99后面的所有元素:", list1, list2);
list1.sort();
list2 = list1;
printList("给list1排序,并且将其赋值给list2:", list1, list2);
list1.unique();
printList("移除所有相邻重复的元素:", list1, list2);
list1.merge(list2);
printList("合并list1和list2到list1中:", list1, list2);
return 0;
}
二 关联式容器
2.1 pair对组
#include <iostream>
#include <forward_list>
#include <string>
#include <algorithm>
#include <iterator>
#include <vector>
using namespace std;
template <typename T1,typename T2>
class MyPair
{
public:
T1 first;
T2 second;
};
int main(void)
{
pair<int, string> p1;
p1.first = 1;
p1.second = "hello world";
MyPair<int, string> p2;
p2.first = 2;
p2.second = "nihao nanjing";
pair<int, string> p3(1,"hello");
pair<int, string> p4 = make_pair(1, "hello world");
cout << p4.first << endl;
cout << p4.second << endl;
string s[10];
int v[10];
for (int i = 0; i < 10; i++)
{
s[i] = "hello";
v[i] = i + 1;
}
vector<pair<string, int>> data;
for (int i = 0; i < 10; i++)
{
data.push_back({s[i],v[i]});
}
for (auto &d : data)
{
cout << d.first << " " << d.second << endl;
}
return 0;
}
2.2 tuple(元组)
一个tuple中可以有任意数量的成员
tuple<int, string, int> t1(1,"zhangsan",12);
cout << std::tuple_size<decltype(t1)>::value << endl;
cout << t1 << endl;
cout << "id = " << std::get<0>(t1) << endl;
cout << "name = " << std::get<1>(t1) << endl;
cout << "age = " << std::get<2>(t1) << endl;
int id;
string name;
int age;
std::tie(id, name, age) = t1;
cout << "id = " << id << endl;
cout << "name = " << name << endl;
cout << "age = " << age << endl;
2.3 set的使用
#include <iostream>
#include <forward_list>
#include <string>
#include <algorithm>
#include <set>
using namespace std;
class Student
{
friend ostream& operator<<(ostream &out, const Student &t);
public:
Student(int i,string n)
{
cout << "student" << endl;
id = i;
name = n;
}
~Student()
{
cout << "~student" << endl;
}
bool operator<(const Student &s) const
{
return this->id < s.id;
}
bool operator>(const Student &s) const
{
return this->id > s.id;
}
private:
int id;
string name;
};
ostream& operator<<(ostream &out, const Student &t)
{
out << "id = " << t.id << " name = " << t.name << endl;
return out;
}
template <typename T,typename U = std::less<T>>
void printSet(const set<T,U> &s)
{
for (auto &s1 : s)
{
cout << s1 << " ";
}
cout << endl;
}
int main(void)
{
Student s1(3, "aa");
Student s2(4, "bb");
Student s3(8, "cc");
Student s4(9, "dd");
Student s5(1, "ee");
Student s6(6, "ff");
Student s7(7, "gg");
set<Student, greater<Student>> s;
s.insert(s1);
s.insert(s2);
s.insert(s3);
s.insert(s4);
s.insert(s5);
s.insert(s6);
s.emplace(s7);
s.emplace(10, "hh");
s.emplace(Student(11,"oo"));
printSet<Student>(s);
cout << "集合大小:" << s.size() << endl;
s.erase(s.begin());
printSet(s);
cout << "set区间删除" << endl;
s.erase(--s.end(), s.end());
printSet(s);
cout << "删除具体的元素" << endl;
s.erase(s1);
printSet(s);
cout << "set的查找" << endl;
auto it = s.find(s2);
if (it == s.end())
{
cout << "对象不存在" << endl;
}
else
{
cout << *it << endl;
}
cout << "set的统计" << endl;
cout << s.count(s6) << endl;
Student ss(0, "bb");
cout << "lower_bound" << endl;
it = s.lower_bound(ss);
if (it == s.end())
{
cout << "不存在" << endl;
}
else
{
cout << *it << endl;
}
cout << "upper_bound" << endl;
it = s.upper_bound(ss);
if (it == s.end())
{
cout << "不存在" << endl;
}
else
{
cout << *it << endl;
}
cout << "equal_range" << endl;
pair<set<Student>::iterator, set<Student>::iterator> p;
p = s.equal_range(ss);
return 0;
}
2.4 map
每个元素都是key/value的pair,其中key是排序的准则,每个key只能出现一次,不许重复,map也被称为
关联式数组,,也就是“索引可以为任意类型”的数组。
#include <iostream>
#include <string>
#include <algorithm>
#include <map>
using namespace std;
template<typename T1,typename T2>
void printMap(const map<T1, T2> &m)
{
for (auto &m1 : m)
{
cout << "key: " << m1.first << " value: " << m1.second << endl;
}
}
int main(void)
{
map<int, string> m;
m.insert(pair<int,string>(3,"aa"));
m.insert(pair<int, string>(4, "bb"));
m.insert(make_pair(5,"cc"));
m.insert(make_pair(6, "dd"));
m.insert(map<int, string>::value_type(7,"ee"));
m.insert(map<int, string>::value_type(8, "ff"));
入
m[9] = "ww";
m[10] = "qq";
m.emplace(11,"tt");
m.emplace_hint(m.begin(), 19, "aa");
printMap(m);
pair<map<int,string>::iterator,bool> p = m.insert(make_pair(5, "ll"));
if (p.second == false)
{
cout << "插入失败" << endl;
cout << "key: " <<p.first->first<< " value: " << p.first->second <<
endl;
}
else
{
cout << "插入成功" << endl;
}
m[3] = "ww";
printMap(m);
cout << "map删除具体元素(根据KEY值删除)" << endl;
m.erase(4);
printMap(m);
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)