C++Primer STL算法

//1.概览:
//  A:beg和end是表示元素范围的迭代器。
//  B:beg2是表示第二个输入序列开始位置的迭代器。end2表示第二个序列的末尾位置,若没有end2,则假定beg2表示的序列至少与beg和end表示的序列一样大。
//  C:dest是表示目的序列的迭代器,对于给定输入序列,算法需要生成多少元素,目的序列必须能保存同样多的元素。
//  D:unaryPred和binaryPry是一元和二元谓语,分别接受一个和两个参数,都是来自输入序列中的元素,两个谓语都返回可用作条件的类型。
//  E:comp:是一个二元谓语,满足关联容器中对关键字序的要求(严格弱序)。注意点:当算法要求容器元素是有序的时候,一般当容器元素是升序排列时,comp功能必须类似于<,当容器元素是降序排列时,comp功能必须类似>,否则会出错。总结:comp的所确定的顺序符合容器前后元素的顺序。
//  F:unaryOp和binaryOp是可调用对象,可分别使用来自输入序列的一个和两个实参调用。

//2.查找对象的算法:
//  A:简单查找算法,要求输入迭代器的算法:
//    find(beg, end, val):返回一个迭代器,指向输入序列中第一个等于val的元素。未找到返回end。
//    find_if(beg, end, unaryPred):返回一个迭代器,指向输入序列中第一个满足unaryPred的元素。未找到返回end。
//    find_if_not(beg, end, unaryPred):返回一个迭代器,指向第一个令unaryPred不成立的元素。未找到返回end。
//    count(beg, end, val):返回一个计数器,指出val出现的次数。
//    count_if(beg, end, unaryPred):返回一个计数器,指出令unaryPred成立的次数。
//    all_of(beg, end, unaryPred):返回一个bool值,指出unaryPred是否对所有元素成立。序列为空返回true。
//    any_of(beg, end, unaryPred):返回一个bool值,指出是否有元素满足unaryPred。序列为空返回false。
//    none_of(beg, end, unaryPred):返回一个bool值,指出是否没有元素能满足unaryPred。序列为空返回true。
//  B:查找重复值的算法,要求前向迭代器:
//    adjacent_find(beg, end)
//    adjacent_find(beg, end, binaryPred):返回指向第一对相邻重复元素的迭代器,若序列中无重复元素则返回end
//    search_n(beg, end, count, val)
//    search_n(beg, end, count, val, binarPred):返回一个迭代器,从此位置开始有count个相等(或满足条件的元素)。不存在则返回end
deInt = [10](0,1,2,3,4,5,6,7,8,9)
auto v = search_n(deInt.begin(), deInt.end(), 4, 2, [](int i, int j){return i > j;}) - deInt.begin();    //v = 3
//  C:查找子序列的算法
//    search(beg1, end1, beg2, end2)
//    search(beg1, end1, beg2, end2, binaryPred):返回第二个序列在第一个序列中第一次出现的位置,未找到返回end
deInt = [10](0,1,2,3,4,5,6,7,8,9) deInt1 = [5](0,1,2,3,4)
auto v = search(deInt.begin(), deInt.end(), deInt1.begin(), deInt1.end(), [](int i, int j){return i - j >= 5;}) - deInt.begin();    //v = 5
//    find_first_of(beg1, end1, beg2, end2)
//    find_first_of(beg1, end1, beg2, end2, binaryPred):返回第二个序列中任意一个元素第一次出现在第一个序列中的位置,未找到返回end
//    find_end(beg1, end1, beg2, end2)
//    find_end(beg1, end1, beg2, end2):类似search,只是返回最后一次出现的位置,若第二个序列为空或未找到则返回end
//  D:其他只读算法:
//    for_each(beg, end, unaryOp):对输入序列中的每个元素应用可调用对象unaryOp
//    mismatch(beg1, end1, beg2)
//    mismatch(beg1, end1, beg2, binaryPred):比较两个序列中的元素,返回一个pair,表示两个序列中第一个不匹配的元素,若均匹配,则pair的first成员为end1,second成员是指向beg2中偏移量等于第一个序列长度的位置
//    equal(beg1, end1, beg2)
//    equal(beg1, end1, beg2, binaryPred):确定两个序列是否相等。相等返回true,不相等返回false

//3.二分搜索算法:(要求容器中的元素必须有序的,若为降序则comp必须使用>,若为升序,则comp必须使用<,当序列的顺序和比较函数不符的时候lower_bound, upper_bound, equal_bound运行会出错,binary_search结果可能会出错)
//  lower_bound(beg, end, val)
//  lower_bound(beg, end, val, comp):返回一个迭代器,若val在序列中,则返回val第一次出现的的位置,否则返回第一个插入val不影响原序列顺序的位置
//  upper_bound(beg, end, val)
//  upper_bound(beg, end, val, comp):返回一个迭代器,若val在序列中,则返回val最后一次出现的位置的下一个位置,否则返回第一个插入val不影响原序列顺序的位置
//  equal_bound(beg, end, val)
//  equal_bound(beg, end, val, comp):返回一个pair,first成员为lower_bound返回的迭代器,second成员为upper_bound返回的迭代器
//deInt = [4](0,1,1,3)
auto v = equal_range(deInt.begin(), deInt.end(), 1, [](int i, int j){return i < j;});
deque<int>::difference_type value0 = v.first - deInt.begin();    //value0 = 1
deque<int>::difference_type value1 = v.second - deInt.begin();    //value1 = 3

//deInt = [4](3,1,1,0)
auto v = equal_range(deInt.begin(), deInt.end(), 1, [](int i, int j){return i > j;});
deque<int>::difference_type value0 = v.first - deInt.begin();    //value0 = 1
deque<int>::difference_type value1 = v.second - deInt.begin();    //value1 = 3

//deInt = [2](0,3)
auto v = equal_range(deInt.begin(), deInt.end(), 1, [](int i, int j){return i < j;});
deque<int>::difference_type value0 = v.first - deInt.begin();    //value0 = 1
deque<int>::difference_type value1 = v.second - deInt.begin();    //value1 = 1
//  binary_search(beg, end, val)
//  binary_search(beg, end, val, comp):返回一个bool值,指出序列中是否含有指定值val。
//  备注:二分搜索算法中的comp是一个比较函数,类似于关联容器中关键字类型的比较函数的要求 

//4.写容器的算法:
//  A:只写不读的算法,要求输出迭代器:
//    fill(beg, end, val)
//    fill_n(dest, cnt, val)
//    generate(beg, end, Gen)
//    generate_n(dest, cnt, Gen):给输入序列的每个元素赋予一个新值。fill将值赋予元素(对于不可拷贝的类型不能用fill),generate执行生成器对象Gen()生成新值。 
deque<unique_ptr<char[]>> deStr(10);
fill(deStr.begin(), deStr.end(), (unique_ptr<char[]>)new char[10]());                    //这句话是错误的
generate(deStr.begin(), deStr.end(), [](){return (unique_ptr<char[]>)new char[10]();});    //正确
//  B:使用输入迭代器的写算法:
//    copy(beg, end, dest)
//    copy_if(beg, end, dest, unaryPred)
//    copy_n(beg, n, dest):从输入范围将元素拷贝到dest指定的序列
//    move(beg, end, dest):对输入序列中的每个元素调用std::move,将其移动到迭代器dest开始的序列
//    transform(beg, end, dest, unaryOp)
//    transform(beg, end, beg2, dest, binaryOp):调用给定操作,将结果写入dest。第一个版本对输入范围中的每个元素应用一元操作,第二个版本对两个输入序列中元素应用二元操作。
//    merge(beg1, end1, beg2, end2, dest)
//    merge(beg1, end1, beg2, end2, dest, comp):两个输入序列都必须有序,将合并后的序列写入dest中。第一个版本使用<,第二个版本使用给定的操作。
//  C:使用前向迭代器的写算法:
//    iter_swap(iter1, iter2):交换iter1和iter2所表示的元素。这两个迭代器可以在同一个容器中,也可以不在同一个容器中。
//    swap_ranges(beg1, end1, beg2):输入范围中的所有元素与beg2开始的第二个序列中所有元素进行交换。注意点:两个范围不能重叠
//    replace(beg, end, old_val, new_val)
//    replace(beg, end, unaryPred, new_val):用new_val替换每个匹配元素。第一个版本使用==,第二个版本使用一元谓语unaryPred
//  D:使用双向迭代器的写算法:
//    copy_backward(beg, end, dest) //backward  [back·ward || 'bækwəd]adj.  向后的
//    move_backward(beg, end, dest):dest是输出序列的尾后迭代器。输入范围内的元素被拷贝或移动到目的序列的尾元素,然后是倒数第二个,类推。
//deInt1 = [10](0,0,0,0,0,0,0,0,0,0) deInt = [2](2,1)
copy_backward(deInt.begin(), deInt.end(), deInt1.end());        //deInt1 = [10](0,0,0,0,0,0,0,0,2,1)
//    inplace_merge(beg, mid, end)
//    inplace_merge(beg, mid, end, comp):将同一序列的两个有序子序列合并为单一有序序列,并写入原序列。第一个版本使用<,第二个版本使用给定的比较操作。注意点:当序列的顺序和给定的比较操作不符的时候将出错。 
//deInt = [4](1,2,-1,0)
inplace_merge(deInt.begin(), deInt.begin() + 2, deInt.end());    //deInt = [4](-1,0,1,2)

//deInt = [4](0,-1,2,1)
inplace_merge(deInt.begin(), deInt.begin() + 2, deInt.end(), [](int i, int j){return i > j;});    //deInt = [4](2,1,0,-1)

//5.划分与排序算法(每个划分和排序算法都提供稳定和不稳定版本,由于前者做了更多的工作,所以其速度比后者慢,其中partial_sort和nth_element只进行部分排序,速度高于整体排序算法):
//  A:划分算法,均要求双向迭代器:
//    is_partitioned(beg, end, unaryPred):如果所有满足谓语unaryPred的元素都在不满足unaryPred的元素之前则返回true(序列为空也返回true),否则返回flase。 partition[par·ti·tion || pɑr'tɪʃn /pɑː't-]n.  分割
//    partition_copy(beg, end, dest1, dest2, unaryPred):将满足unaryPred的元素拷贝到dest1,将不满足unaryPred的元素拷贝到dest2。返回一个pair,分别保存两个输出序列的被拷贝的元素的末尾。输入序列与两个目的序列不能重叠。
//    partition_point(beg, end, unaryPred):输入序列必须是用unaryPred划分过的,返回满足unaryPred的范围的尾后迭代器。
//    stable_partition(beg, end, unaryPred)
//    partition(beg, end, unaryPred):使用unaryPred划分输入序列,满足unaryPred的元素放在序列开始,不满足unaryPred的元素放在序列尾部,返回一个迭代器,指向最后一个满足unaryPred的元素之后的元素,若所有元素均不满足unaryPred则返回beg
//  B:排序算法,均要求随机访问迭代器。每个排序算法均提供两个版本,一个版本使用元素的<运算符来比较元素,另一个版本接受一个额外的参数来指定排序关系:
//    sort(beg, end)
//    stable_sort(beg, end)
//    sort(beg, end, comp)
//    stable_sort(beg, end, comp):排序整个范围
//    is_sorted(beg, end)
//    is_sorted(beg, end, comp):返回一个bool值,指出整个输入序列是否有序
//    is_sorted_until(beg, end)
//    is_sorted_until(beg, end, comp)://vs2010下返回最后一个符合comp的元素的迭代器 vs2012下返回第一个不符合comp的元素的迭代器
//    partial_sort(beg, mid, end)
//    partial_sort(beg, mid, end, comp):将mid-beg个元素(这些元素是:假定将beg到end中的元素按照指定比较操作排序后,位于beg到mid中的元素)排序放置在beg开始的位置。排序后,从beg到mid中的元素都是有序的,mid到end中的元素都是无序的。partial [par·tial || 'pɑrʃl /'pɑː-]adj. 部分的
//    partial_sort_copy(beg, end, destBeg, destEnd)
//    partial_sort_copy(beg, end, destBeg, destEnd, comp):排序输入范围内的元素,并将足够多的元素拷贝到destBeg和destEnd所指示的序列中。如果目的序列大于等于输入范围则排序整个输入序列并存入输出序列,若目的序列小于输入范围,则拷贝输入序列中与目的范围一样多的元素。
//    nth_element(beg, nth, end)
//    nth_element(beg, nth, end, comp):参数nth是一个指向输入序列的一个迭代器。执行此函数后,序列中的元素都会按照比较操作定义的顺序围绕nth所指的元素进行划分。

//6.通用重排操作:
//  A:使用前向迭代器的重排算法,三个重排算法提供拷贝的版本,这些拷贝的版本完成相同的重排工作,但将重排后的元素写入输出序列而不改变原序列:
//    remove(beg, end, val)
//    remove_if(beg, end, unaryPred)
//    remove_copy(beg, end, dest, val)
//    remove_copy_if(beg, end, dest, unaryPred):从序列中删除元素,采用的办法是:用保留的元素覆盖要删除的元素。算法返回一个迭代器,指向最后一个保留元素的尾后位置。
//    unique(beg, end)
//    unique(beg, end, binaryPred)
//    unique_copy(beg, end, dest)
//    unique_copy(beg, end, dest, binaryPred):重排序列,对于相邻的满足条件的元素,通过覆盖来进行删除,返回一个迭代器,指向最后一个保留元素的尾后位置。
//    rotate(beg, mid, end)
//    rotate_copy(beg, mid, end, dest):围绕mid指向的元素进行元素转动。元素mid成为首元素,随后是mid+1->end之间的之前的元素,再接着是beg到mid之前的元素。返回一个迭代器,指向原来beg位置的用元素。
//  B:使用双向迭代器的重排算法:  
//    reverse(beg, end)
//    reverse_copy(beg, end, dest):翻转序列中的元素
//  C:使用随机访问迭代器的重排算法:
//    random_shuffle(beg, end):混乱重排输入序列的元素
//    random_shuffle(beg, end, rand):待研究    random[ran·dom || 'rændəm]adj.  任意的
//    shuffle(beg, end, Uniform_rand):待研究   shuffle[shuf·fle || 'ʃʌfl]n.混乱
//  D:排列算法,排列算法生成序列的字典序排列。对于一个给定序列,这些算法通过重排它的一个排列来生成字典序中的下一个或前一个排列,算法返回一个bool值指出是否存在这样的排列。这些算法假定序列中的元素是唯一的。要求双向迭代器:
//    next_permutation(beg, end): permutation[per·mu·ta·tion || ‚pɜrmjə'teɪʃn /‚pɜːmjʊ-]n.  交换, 排列
//    next_permutation(beg, end, comp):如果序列已经是最后一个排序,则本函数将序列重排为最小的序列,返回false。否则将输入序列转为字典序的下一个排列,返回true。第一个版本使用<,第二个版本使用comp。
//    prev_permutation(beg, end)
//    prev_permutation(beg, end, comp):若序列已经是第一个排序,则本函数将序列重排为最大的序列,返回false。否则将序列转为字典序的上一个排序,返回true。第一个版本使用<,第二个版本使用comp。
//  E:有序序列的集合算法,这些算法需要输入迭代器,接受一个表示目的序列的输出迭代器(includes除外)。这些算法返回一个指向dest最后一个写入元素的尾后迭代器。第一个版本均使用<,第二个版本使用comp:  
//    includes(beg, end, beg2, end2)
//    includes(beg, end, beg2, end2, comp):如果第二个序列中的每个元素都包含在输入序列中则返回true(这里使用的是==),否则返回false。第一个版本使用<指示元素为升序,第二个版本使用comp来确定元素的顺序(<和comp仅确定容器的元素顺序)。
//    set_union(beg1, end1, beg2, end2, dest)
//    set_union(beg1, end1, beg2, end2, dest, comp):对两个序列中的所有元素,创建它们的有序序列,两个元素均包含的元素只在输出元素中出现一次。输出序列保存在dest中。
//    set_intersection(beg1, end1, beg2, end2, dest)
//    set_intersection(beg1, end1, beg2, end2, dest, comp):对两个输入序列中均包含的元素创建它们的有序序列,保存在dest中。
//    set_difference(beg1, end1, beg2, end2, dest)
//    set_difference(beg1, end1, beg2, end2, dest, comp):对出现在第一个序列但不出现在第二个序列中的元素创建一个有序序列,保存在dest中
//    set_symmetric_difference(beg1, end1, beg2, end2, dest)
//    set_symmetric_difference(beg1, end1, beg2, end2, dest, comp):对只出现在一个序列中的元素,创建一个有序序列,保存在dest中。 symmetric[sym·met·ric || sɪ'metrɪk(l)]adj. 相称性的;
//  F:最小值和最大值,使用元素的<运算符或给定比较操作。第一组算法对值而非序列进行操作。第二组算法接受一个序列,要求输入迭代器:
//    min(val1, val2)
//    min(val1, val2, comp)
//    max(val1, val2)
//    max(val1, val2, comp):返回val1/val2之间的最小/最大值。两个实参类型必须完全一致。参数和返回类型都是const的引用,意味着对象不会被拷贝。
//    minmax(val1, val2)
//    minmax(val1, val2, comp):返回一个pair,其first是较小着,second是较大者。
//    min_element(beg, end)
//    min_element(beg, end, comp):返回给定序列中的最小值
//    max_element(beg, end)
//    max_element(beg, end, comp):返回给定序列中的最大值
//    minmax_element(beg, end)
//    minmax_element(beg, end, comp):返回一个pair,first成员为最小元素,second成员为最大元素。
//  G:字典序比较:  
//    lexicographical_compare(beg1, end1, beg2, end2): lexicographical 英[leksɪkə'græfɪkl] 美[leksɪkə'græfɪkl] adj.    词典编纂的
//    lexicographical_compare(beg1, end1, beg2, end2, comp):如果第一个序列在字典序中小于第二个序列,则返回true,否则返回false。第一个版本使用<,第二个版本使用comp。

//7.数值算法,定义在头文件numeric中,这些算法要求输入迭代器,如果算法输出数据,则使用输出迭代器表示目的位置:
//  accumulate(beg, end, init)
//  accumulate(beg, end, init, binaryOp):返回输入序列所有值的和。和的初始值由init指定。返回类型和init的类型相同。第一个版本使用+,第二个版本使用binaryOp。
//  inner_product(beg1, end1, beg2, init):备注:利用此函数可以很方便的算一个序列的平方和。  product    英[ˈprɒdʌkt]美[ˈprɑ:dʌkt]n.    产品; 乘积
//  inner_product(beg1, end1, beg2, init, binOp1, binOp2):返回两个序列的内积。和的初始值由init指定,返回类型和init相同。第一个版本使用* +,第二个版本使用binOp1,binOp2。
//  partial_sum(beg, end, dest)
//  partial_sum(beg, end, dest, binaryOp):将新序列写入dest,每个新元素的值为输入范围当前位置和之前位置上所有元素之和。第一个版本使用+,第二个版本使用binaryOp
//  adjacent_difference(beg, end, dest)
//  adjacent_difference(beg, end, dest, binaryOp):将新序列写入dest,每个新元素(除了首元素)的值都为输入范围中当前位置和前一个位置元素之差。第一个版本使用-,第二个版本使用binaryOp。
//  iota(beg, end, val):将val赋予首元素,并将递增后的值赋予下一元素,直至结束。val可以是一个字面值常量。