目录
3.1 list.sort() vs 算法里面的sort()

typedef basic_string<char> string;
实际上string是类模板库中实例化的一个类(实例化的类型为char)
学习使用就是要学习这个类提供了哪些接口,string常用的接口如下
- string s2("123434");
- string::iterator it = s2.begin();
- //string::const_iterator it = s2.cbegin();//带const的迭代器,只读不写
- while (it != s2.end())
- {
- *it += 1;//可写
- cout << *it << " ";//可读
- ++it;
- }
- cout << endl;
反向迭代器:逆序遍历
- string s2("123434");
- string::reverse_iterator rit = s2.rbegin();
- while (rit != s2.rend())
- {
- cout << *rit << " ";
- ++rit;
- }
- cout << endl;
- string s3 = "dsssds";
- //for (auto& e : s3)//auto是自动类型推导,知道类型的时候可以直接写char
- for (char& e : s3)//写的时候要加引用
- {
- e += 1;
- cout << e << " ";
- }
- cout << endl;
其实是一个类模板,通用数组
常用接口如下:
- string s("hello");
- vector<char> v4(s.begin(), s.end());
- //string和vector<char>的区别,有无\0
- vector<int> v;
- v.push_back(1);v.push_back(2);v.push_back(3);v.push_back(4);v.push_back(5);v.push_back(6);
-
- //(1)步骤一:元素3的前面插入一个30
- //find提供了函数模板
- //template <class InputIterator, class T>
- //InputIterator find (InputIterator first, InputIterator last, const T& val);
- //找到了就返回位置,没找到就返回last迭代器
- vector<int>::iterator pos = find(v.begin(), v.end(), 3);
- if (pos != v.end()){
- v.insert(pos, 30);
- }
-
- // (2)步骤2:删除元素3
- //(情况一迭代器失效)pos在insert以后就失效了,此时pos的位置是30,所以要重新找3
- //(情况二迭代器失效)insert之后,增容了(新开辟了一段空间),原来pos位置被释放了,pos是野指针了
- pos = find(v.begin(), v.end(), 3);
- if (pos != v.end()){
- v.erase(pos);
- }
例如:要求删除v中所有的偶数
- vector<int> v;
- v.push_back(1);v.push_back(2);v.push_back(3);v.push_back(4);v.push_back(5);v.push_back(6);v.push_back(7);
-
- vector<int>::iterator it = v.begin();
- while (it != v.end())
- {
- if (*it % 2 == 0){
- // erase(it)以后 it失效,不能++,
- // ***特别注意*** :erase是有返回值的,会返回删除位置it的下一个位置
- it = v.erase(it);
- }
- else{
- ++it;
- }
- }
提供vector的成员函数swap
和全局函数swap
- vector<int> v1;
- v1.push_back(1);v1.push_back(2);v1.push_back(3);
- vector<int> v2;
- v2.push_back(10);v2.push_back(20);
-
- // C++98 推荐第2个方法;C++11中都一样
- swap(v1, v2);//交换方法1
- v1.swap(v2); //交换方法2
双向循环带头链表
常见的迭代器的分类:
因为算法里的sort底层使用的是快速排序,快速排序要求容器迭代器必须得是随机迭代器(能够随机访问,比如a[i]),因为快排要三数取中优化,不支持随机访问,效率就不够了。
但是list的迭代器不是随机的,是双向的,所以不能调用算法里面的sort,只能用自己的成员函数接口。而vector、string等的迭代器是随机的,可以支持算法里的sort
- int a[] = { 16, 2, 77, 29 };
- list<int> lt1(a, a + 4); //实际是迭代区间构造函数,list (InputIterator first, InputIterator last)
- //原生指针可以当做天然的迭代器,其实vector/string的迭代器也是原生指针
- lt1.sort();
- //sort(lt1.begin(), lt1.end());//这里不行,因为算法里面的sort需要随机迭代器,而list的迭代器只支持双向++或--,并不是随机的
- int a[] = { 16, 2, 77, 29 };
- vector<int> v(a, a + 4); //
- sort(v.begin(), v.end());//默认是升序
- //sort(v.begin(), v.end(), greater<int>()); //降序 原理是仿函数
list中insert不会导致迭代器失效
erase会导致失效
- list<int> lt;
- lt.push_back(1);lt.push_back(2);lt.push_back(3);
-
- list<int>::iterator pos = find(lt.begin(), lt.end(), 3);
- lt.insert(pos, 30);
- cout << *pos << endl; //这里pos位置仍然是3
- // vector insert会导致pos失效,list会不会呢?不会
-
- lt.erase(pos);// vector erase会导致pos失效,list会不会呢? 会
- //cout << *pos << endl;//这里pos已经找不到3了
- list<int> lt;
- lt.push_back(1);lt.push_back(2);lt.push_back(2);lt.push_back(2);
- lt.push_back(3);lt.push_back(4);lt.push_back(4);lt.push_back(2);
- lt.sort();// 一般情况,不太建议用list的排序,效率不是很高
- lt.unique();//去重、只能去连续的数据的重,所以要先排序
- //最后元素应该为:1 2 3 4
deque功能上是list和vector的结合体。可以头插、尾插、又可以用下标进行随机访问
底层是中控器,类似于动态开辟的二维数组。
但是并不能用deque来代替vector和list
deque适合头尾插入删除,但不适合大量的中间插入删除、也不适合大量的随机访问;
deque一般是作为stack和queue的默认适配容器
访问方式:
stack常用接口:
- stack<int> st;
- st.push(1);st.push(2);st.push(3);st.push(4);
-
- while (!st.empty()){
- cout << st.top() << " ";
- st.pop();
- }
- // 4 3 2 1
queue常用接口:
- queue<int> q;
- q.push(1);q.push(2);q.push(3);q.push(4);
-
- while (!q.empty()){
- cout << q.front() << " ";
- q.pop();
- }
- //1 2 3 4
优先级队列,实际上底层是一个堆,默认是大堆,访问时大到小的降序
- // 默认是一个大堆,默认大的优先级高(也就是堆顶top元素为最大) less
- priority_queue<int> pq;//打印出来为大到小降序
-
- // 怎么变成小堆,堆顶元素为最小的, greater仿函数
- //priority_queue<int, vector<int>, greater<int>> pq;//打印出来为小到大升序
- // 其中第二个参数vector<>是用来承载底层数据结构堆(heap)的容器;第三个参数less<>或者greater<>是对第一个参数的比较类,less<int>表示数字越大优先级越大,greater<int>表示数字越小,优先级越大。
-
- pq.push(2);pq.push(5);pq.push(3);pq.push(1);
- while (!pq.empty()){
- cout << pq.top() << " ";
- pq.pop();
- }
- cout << endl;
仿函数(functor),就是使一个类的使用看上去像一个函数。其实现就是类中实现一个operator(),这个类就有了类似函数的行为,就是一个仿函数类了。
- struct LessInt//仿函数
- {
- bool operator()(int l, int r) //类里面对函数调用运算符重载了
- {
- return l < r;
- }
- };
- bool func(int l, int r)//这是正常函数
- {
- return l < r;
- }
- int main(){
- LessInt le;
- cout << le.operator()(1, 3) << endl;
- cout << le(1, 3) << endl;//类对象可以像函数一样使用
- cout << LessInt()(1, 3) << endl;
- cout << func(1, 3) << endl; //正常函数的使用
- }