C++容器

STL

标准库都应该被封装到std空间中

顺序容器

容器没有足够空间执行push_back()这类添加元素的操作时
重新分配(比预计更多)新内存,移动原元素,释放旧内存

#define cap vector/string/deque
cap.shrink_to_fit();  //裁剪至size()大小,退回多余空间

#define cap vector/string
cap.capacity();       //不重新分配内存的条件下,c可以保存多少元素
cap.reserve(n);       //n>capacity()时,重新分配>=n个元素的空间,实现不一样可能翻倍
                      //n<=capacity()时,不会退回空间,什么也不做
string s1,s2;
s1.append("");
s1.insert(pos,"");
s1.erase(pos,n);
s1.assigned(pos,n);  //s1=*pos[0~n-1]赋值
s1.replace(pos,n,""); //pos删n插入""
s1.compare(s2);
s1.compare(pos1,n1,s2,pos2,n2); //字典序比较结果
string s3=to_string(i);
double d=stod(s3);
string s4("-3.14");
d=stod(s4.substr(s4.find_first_of("+-.0123456789")));

适配器adaptor
一个类型(函数)A的适配器接受一种已有类型(函数)B,使B的行为看起来像A
容器、迭代器、函数都有适配器
默认构造函数=空对象
接收的容器,其构造函数会拷贝容器中的元素(要求容器有添加、删除以及访问队尾元素的能力)

deque<int> deq({1,2,3,4,5,6});
stack<int> stk(deq);                   //  <T,C<T>>   默认C<T>为deque
vector<int> vec({1,2,3,4,5,6});
stack<int vector<int>> stk1(vec)
	while (!stk.empty())
	{
		cout << stk.top() << endl; //输出6,5,4,3,2,1,stk从deq[0~6]压入栈
		stk.pop();
	}

泛型算法

算法接受任何可调用对象(callable object)
1.函数 或 函数指针
2.对调用运算符"()"进行了重载的类
3.lambda表达式(lambda expression)

算法依赖于元素类型的操作,操作依赖于运算符
应该依赖于迭代器操作,不应该具有增删(inserter除外)的能力

#include<algorithm>

auto res=find(vec.cbegin(),vec.cend(),val); //cbegin()、cend()返回const迭代器
if(res==vec.cend())cout<<"没找到"<<endl;  //使用迭代器,即任何容器(包括数组)都可以使用

int sum=accumulate(vec.cbegin(),vec.cend(),/*initializer*/); 
//initializer决定了accumulate中"+"的重载形式
string sum=accumulate(vec.cbegin(),vec.cend(),string("")); //string有实现"+"重载
string sum=accumulate(vec.cbegin(),vec.cend(),"");     错误//const char*没有"+"的重载

bool equal(v1.cbegin(),v1.cend(),v2.cbegin()); //序列二长于序列一,不会抛异常!!!
//只要能用"==",元素类型不必一样 vector<string> 和 list<const char*>

fill(v.cbegin(),v.cend(),/*val*/); 
fill_n(dest,n,val); //注意越界

返回v2队尾 = copy(v1.cbegin(),v1.cend(),v2); //v1拷贝到v2
replace(v1.cbegin(),v2.cend(),/*v1被替换元素*/,/*替换元素*/);

#include<iterator>
back_insert_iterator<_Container> back_inserter(_Container& _Cont);
//使用 back_insert_iterator 能够提供新的空间插入新元素 个人喜欢称为 尾后插入迭代器
//source code
back_insert_iterator& operator=(typename _Container::value_type&& _Val) 
{    // push value into container
     container->push_back(_STD move(_Val)); //可以看到只能在队尾添加新的元素!!!
     return *this;
}

replace(v1.cbegin(),v2.cend(),back_inserter(vec),item1,item2); //替换拷贝存入vec中

sort(v.begin(),v.end());//43212121 -> 11122234
auto end_unique=unique(v.begin(),v.end()); //覆盖相邻的重复元素 1234|2234
erase(end_unique,v.end()); //删除重复的元素

谓词(predicate)

一个可调用表达式,返回条件运算结果
元素类型必须能转化为参数的类型,且只接受一个或两个参数
一元谓词(unary predicate)二元谓词(binary predicate)

bool isShorter(string &s1,string &s2){
   return s1.size()<s2.size();
}
sort(vec.begin(),vec.end(),isShorter);

函数指针!!

typedef int (*funp)(int, int)   //funp为指针类型
typedef decltype(fun), *p;   //decltype返回函数类型,所以p为指针
int fun(int a,int b){return 1;}
funp fp=&fun;                      //指针
int a = fp(1,2);                    //可以不用解引用

返回函数指针时比较特殊

using F = int(int, int);       //fun为函数类型 的 类型别名
using FP = int(*)(int,int);  //FP为指针
FP fun(int, int){return FP();}  //返回的是函数的指针,注意不允许返回函数对象
int (*fun(int))(int ,int);       //等价,fun接收(int)参数,返回指向int (int, int)函数的指针
auto fun(int)  -> int(*)(int, int); //尾置返回类型更清晰

lambda表达式

算法 为了接收比谓词(两个)更多的参数,使用lambda表达式
lambda表达式可以看成一个未命名的内联函数
适合在只会用一两次的地方使用

fun()
{
    int a=0;
    auto f=[a](){return a>0;}  //值传递
    auto res=f();  //auto = bool 自动推断
}

[capture list](parameter list)->return_type {function body}
[捕获列表] 传递局部(非static)变量
隐式捕获:=(值)或&(引用) eg:[&,names] //隐式引用捕获,names声明值捕获,反之亦然
(参数列表) 可省 没有默认值
返回类型 默认void 使用尾置返回 或 仅有return语句时auto推测
{函数体}

编译器创建一个与lambda对应的类类型,传递给函数时,实例化一个该类型的对象
值传递 :变量在对象创建时被拷贝 const(需要mutable才能赋值)
引用传递:lambda内外变化相互影响 引用决定是否const
数据成员在创建后可能会多次被调用,尽量避免捕获指针或引用

//-------------------------使用示例-------------------------------
void biggies(vector<string>& w,vector<string>::size_type sz)
{
  sort(w.begin(),w.end());//排序
  auto unique_end=unique(w.begin(),w.end()); //去重
  w.erase(unique_end,w.end()); 
  stable_sort(w.begin(),w.end(),             //相等的元素维持原顺序
              [](const string &l,const string &r){return l.size()<r.size();})
  auto  it = find_if(v.begin(),v.end(),[sz]const(string &a){return a.size()>=sz;});
  //将sz传递进去才可以在函数体中使用
  for_each(it,w.end(),[](const string &s){cout<<s<<" ";}); 
  //按字典序打印所有长度>=sz的元素
  cout<<endl;
}
//--------------------实现-----------------
template <class _Pr, class _Ty1, class _Ty2>
constexpr bool _Debug_lt_pred(_Pr&& _Pred, 
                              _Ty1&& _Left, 
                              _Ty2&& _Right) 
_NOEXCEPT_COND(noexcept(_Pred(_Left, _Right))&& noexcept(_Pred(_Right, _Left))) 
{ // test if _Pred(_Left, _Right) and _Pred is strict weak ordering
    const auto _Result = static_cast<bool>(_Pred(_Left, _Right));
    //返回值会被强制转换为 bool 类型
    if (_Result) { 
    //可以看到每个algorithm对lambda表大式是有不同要求的,这里要求两元素相比的形式
        _STL_VERIFY(!_Pred(_Right, _Left), "invalid comparator"); 
    }
    return _Result;
}

#define _DEBUG_LT_PRED(pred, x, y) _Debug_lt_pred(pred, x, y)
//----------------------------可以看到source code使用快速排序------------------
template <class _RanIt, class _Pr>
inline void _Sort_unchecked(
    _RanIt _First, _RanIt _Last, _Iter_diff_t<_RanIt> _Ideal, _Pr _Pred) { 
    // order [_First, _Last), using _Pred
    _Iter_diff_t<_RanIt> _Count;
    while (_ISORT_MAX < (_Count = _Last - _First) && 0 < _Ideal) { 
        // divide and conquer by quicksort
        auto _Mid = _Partition_by_median_guess_unchecked(_First, _Last, _Pred);
        // TRANSITION, VSO#433486
        _Ideal = (_Ideal >> 1) + (_Ideal >> 2); // allow 1.5 log2(N) divisions

        if (_Mid.first - _First < _Last - _Mid.second) { // loop on second half
            _Sort_unchecked(_First, _Mid.first, _Ideal, _Pred);
            _First = _Mid.second;
        } else { // loop on first half
            _Sort_unchecked(_Mid.second, _Last, _Ideal, _Pred);
            _Last = _Mid.first;
        }
    }

    if (_ISORT_MAX < _Count) { // heap sort if too many divisions
        _Make_heap_unchecked(_First, _Last, _Pred);
        _Sort_heap_unchecked(_First, _Last, _Pred);
    } else if (2 <= _Count) {
        _Insertion_sort_unchecked(_First, _Last, _Pred); // small
    }
}

参数绑定

bind标准库

关联容器

multi
map{key-value} / set{key}multimap / multiset
unordered
hash_map
unordered_set / unordered_mapunordered_multi_set / unordered_multi_map

有序容器对“关键字的类”要求能比较(同算法,严格弱序,strict weak ordering,实现<比较)

#include<map>
#include<set>
#include<unordered_map>
#include<unordered_set>
#include<string>
#include<iostream>
using namespace std;
bool com(string &a,string &b)  //比大小的函数用于排序
{  return a.size<b.size;  }
int main()
{
    map<string,int>wl={{"hk",1},{"cb",1},{"kz",1}};
    set<string,bool(*)(string&,string&)> ex({"the","or"},&com);
    string w;
    while(cin>>w)
       if(ex.find(w)==ex.end()) //不在set中的单词才进入map,返回在set中的iterator
             wl[w]++;
    for(const pair<string,int> &w:wl) //Sorce Code就是pair<key,value>实现的
    cout<<w.first<<":"<<w.second<<endl;
    while(1);
    return 0;
}

STL实现

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值