STL中的算法小结
1 (1)要运用STL的算法,首先必须包含头文件<algorithm>,某些STL算法用于数值处理,因此被定义于头文件<numeric> 2 3 (2)所有STL算法都被设计用来处理一个或多个迭代器区间,第一个区间通常以起点和终点表示,至于其他区间,多数情况下你只需提供起点便足以,其终点可以自动以第一个区间的元素数量推断出来,调用者必须保证这些区间的有效性。 4 STL算法采用覆盖模式而非安插模式,所以调用者必须保证目标区间拥有足够的元素空间,当然你也可以运用特殊的安插型迭代器将覆盖模式改变为安插模式。 5 6 (3)尾词_if:如果算法有两种形式,参数个数都相同,但第一形式的参数要求传递一个值,第二形式的参数要求传递一个函数或仿函数,那么尾词_if就派上了用场,无尾词的那个要求传递数值,有尾词的那个要求传递函数或仿函数。不过并非所有“要求传递仿函数”的算法都有尾词_if,如果算法以额外参数来接受这样的函数或仿函数,那么不同版本的算法就可以采用相同的命名。 7 尾词_copy:这个尾词用来表示在此算法中,元素不光被操作,还会被复制到目标区间。 8 9 (4)for_each()算法: 10 UnaryProc for_each (InputIterator beg, InputIterator end, UnaryProc op); 11 1对区间[beg, end)中的每一个元素调用op(elem) 12 2返回op(已在算法内部被变动过)的一个副本 13 3op的任何返回值都会被忽略 14 4op可以变动元素 15 5复杂度:线性 16 17 (5)元素计数算法: 18 difference_type count (InputIterator beg, InputIterator end, const T& value); 19 difference_type count_if (InputIterator beg, InputIterator end, UnaryPredicate op); 20 1第一形式会计算区间[beg, end)中的元素等于value的元素个数 21 2第二形式会计算区间[beg, end)中令以下一元判断式结果为true的元素个数:op(elem) 22 3返回值型别为difference_type,是表现迭代器间距的型别 23 4注意op在函数调用过程中不应该改变自身状态 24 5op不应该改动传进来的参数 25 6关联式容器(set/multiset,map/multimap)提供了一个等效的成员函数count()用来计算等于某个value或key的元素个数 26 7时间复杂度:线性 27 28 (6)最大最小值算法: 29 InputIterator min_element (InputIterator beg, InputIterator end); 30 InputIterator min_element (InputIterator beg, InputIterator end, CompFunc op); 31 InputIterator max_element (InputIterator beg, InputIterator end); 32 InputIterator max_element (InputIterator beg, InputIterator end, CompFunc op); 33 1所有这些算法都返回区间[beg, end)中的最大或最小值的位置 34 2上述无op参数版本以operator<进行元素比较 35 3op用来比较两个元素:op(elem1, elem2)如果第一个元素小于第二个元素,应当返回true 36 4如果存在多个最大或最小值,上述算法返回找到的第一个最大或最小值 37 5op不应该改动传进去的参数 38 6时间复杂度:线性 39 40 (7)搜寻元素算法: 41 InputIterator find (InputIterator beg, InputIterator end, const T& value); 42 InputIterator find_if (InputIterator beg, InputIterator end, UnaryPredicate op); 43 1第一形式返回区间[beg, end)中的第一个“元素值等于value”的元素位置 44 2第二形式返回区间[beg, end)中令一元判断式op(elem)结果为true的第一个元素的位置 45 3如果没有找到匹配元素,两种形式都返回end 46 4注意op在函数调用过程中不应该改变自身状态 47 5op不应该改动传进来的参数 48 6如果是已序区间,应使用lower_bound(),upper_bound(),equal_range()或binary_search()算法以获取更高的性能 49 7关联式容器(set/multiset,map/multimap)提供了一个等效的成员函数find(),拥有对数时间复杂度 50 8时间复杂度:线性 51 52 InputIterator search_n (InputIterator beg, InputIterator end, Size count, const T& value); 53 InputIterator search_n (InputIterator beg, InputIterator end, Size count, const T& value, BinaryPredicate op); 54 1第一形式返回区间[beg, end)中的第一组“连续count个元素值全等于value”的元素位置 55 2第二形式返回区间[beg, end)中的第一组“连续count个元素使op(elem, value)结果为true”的元素位置 56 3如果没有找到匹配元素,两种形式都返回end 57 4注意op在函数调用过程中不应该改变自身状态 58 5op不应该改动传进来的参数 59 6时间复杂度:线性 60 61 ForwardIterator1 search (ForwardIterator1 beg, ForwardIterator1 end, ForwardIterator2 searchBeg, ForwardIterator2 searchEnd); 62 ForwardIterator1 search (ForwardIterator1 beg, ForwardIterator1 end, ForwardIterator2 searchBeg, ForwardIterator2 searchEnd, BinaryPredicate op); 63 1两种形式都返回区间[beg, end)内“和区间[searchBeg, searchEnd)完全吻合”的第一个子区间内的第一个元素位置 64 2第一形式中,子区间元素必须完全等于[searchBeg, searchEnd)的元素 65 3第二形式中,子区间元素和[searchBeg, searchEnd)的对应元素必须使op(elem, searchElem)结果为true 66 4如果没有找到匹配子区间,两种形式都返回end 67 5注意op在函数调用过程中不应该改变自身状态 68 6op不应该改动传进来的参数 69 7时间复杂度:线性 70 71 ForwardIterator find_end (ForwardIterator beg, ForwardIterator end, ForwardIterator searchBeg, ForwardIterator searchEnd); 72 ForwardIterator find_end (ForwardIterator beg, ForwardIterator end, ForwardIterator searchBeg, ForwardIterator searchEnd, BinaryPredicate op); 73 1两种形式都返回区间[beg, end)内“和区间[searchBeg, searchEnd)完全吻合”的最后一个子区间内的第一个元素位置 74 2第一形式中,子区间元素必须完全等于[searchBeg, searchEnd)的元素 75 3第二形式中,子区间元素和[searchBeg, searchEnd)的对应元素必须使op(elem, searchElem)结果为true 76 4如果没有找到匹配子区间,两种形式都返回end 77 5注意op在函数调用过程中不应该改变自身状态 78 6op不应该改动传进来的参数 79 7时间复杂度:线性 80 81 ForwardIterator find_first_of (ForwardIterator1 beg, ForwardIterator1 end, ForwardIterator2 searchBeg, ForwardIterator2 searchEnd); 82 ForwardIterator find_first_of (ForwardIterator1 beg, ForwardIterator1 end, ForwardIterator2 searchBeg, ForwardIterator2 searchEnd, BinaryPredicate op); 83 1第一形式返回第一个“既在区间[beg, end)中出现,也在区间[searchBeg, searchEnd)中出现”的元素位置 84 2第二形式返回区间[beg, end)中的第一个这样的元素:他和区间[searchBeg, searchEnd)内的每一个元素进行op(elem, searchElem)结果都为ture 85 3如果没有找到匹配元素,两种形式都返回end 86 4注意op在函数调用过程中不应该改变自身状态 87 5op不应该改动传进来的参数 88 6你可以使用逆向迭代器来搜寻最后一个这样的元素 89 7时间复杂度:线性 90 91 InputIterator adjacent_find (InputIterator beg, InputIterator end); 92 InputIterator adjacent_find (InputIterator beg, InputIterator end, BinaryPredicate op); 93 1第一形式返回区间[beg, end)中的第一对“连续两个相等元素”之中的第一个元素位置 94 2第二形式返回区间[beg, end)中的第一对“连续两个元素均使op(elem, nextElem)结果为true“的其中第一个元素位置 95 3如果没有找到吻合元素,两种形式都返回end 96 4注意op在函数调用过程中不应该改变自身状态 97 5op不应该改动传进来的参数 98 6时间复杂度:线性 99 100 bool equal (InputIterator1 beg, InputIterator1 end, InputIterator2 cmpBeg); 101 bool equal (InputIterator1 beg, InputIterator1 end, InputIterator2 cmpBeg, BinaryPredicate op); 102 1第一形式判断区间[beg, end)内的元素是否都和以cmpBeg开头的区间内的元素相等 103 2第二形式判断区间[beg, end)内的元素和以cmpBeg开头的区间内的对应元素是否都能使op(elem, cmpElem)结果为true 104 3调用者必须保证以cmpBeg开头的区间具有足够的元素 105 4当序列不相等时,如果想要了解其间的不同,应使用mismatch()算法 106 5注意op在函数调用过程中不应该改变自身状态 107 6op不应该改动传进来的参数 108 7时间复杂度:线性 109 110 pair<InputIterator1, InputIterator2> mismatch (InputIterator1 beg, InputIterator1 end, InputIterator2 cmpBeg); 111 pair<InputIterator1, InputIterator2> mismatch (InputIterator1 beg, InputIterator1 end, InputIterator2 cmpBeg, BinaryPredicate op); 112 1第一形式返回区间[beg, end)和以cmpBeg开头的区间之中的第一组两两相异的对应元素 113 2第二形式返回区间[beg, end)和以cmpBeg开头的区间之中的第一组”使op(elem, cmpElem)结果为false“的对应元素 114 3如果没有找到相异点,就返回一个pair,以end和第二序列的对应元素组成。这并不意味着两个序列相等,因为第二序列有可能包含更多的元素 115 4调用者必须保证以cmpBeg开头的区间具有足够的元素 116 5如果想要了解两个序列是否相等,应使用equal()算法 117 6注意op在函数调用过程中不应该改变自身状态 118 7op不应该改动传进来的参数 119 8时间复杂度:线性 120 121 bool lexicographical_compare (InputIterator1 beg1, InputIterator1 end1, InputIterator2 beg2, InputIterator2 end2); 122 bool lexicographical_compare (InputIterator1 beg1, InputIterator1 end1, InputIterator2 beg2, InputIterator2 end2, CompFunc op); 123 1两种形式都用来判断区间[beg1, end1)的元素是否小于区间[beg2, end2)的元素。所谓”小于“是指本着”字典次序“的意义 124 2第一形式使用operator< 125 3第二形式使用op(elem1, elem2)来判断 126 4注意op在函数调用过程中不应该改变自身状态 127 5op不应该改动传进来的参数 128 6时间复杂度:线性 129 130 (8)复制元素算法: 131 OutputIterator copy (InputIterator sourceBeg, InputIterator sourceEnd, OutputIterator destBeg); 132 BidirectionalIterator1 copy_backward (BidirectionalIterator1 sourceBeg, BidirectionalIterator1 sourceEnd, BidirectionalIterator2 destEnd); 133 1这两个算法都将源区间[sourceBeg, sourceEnd)中的所有元素复制到以destBeg为起点或以destEnd为终点的目标区间里去 134 2返回目标区间内最后一个被复制的元素的下一个位置,也就是第一个未被覆盖的元素的位置 135 3destBeg或destEnd不可处于[sourceBeg, sourceEnd)区间内 136 4copy()正向遍历序列,copy_backward()逆向遍历序列 137 5STL没有所谓的copy_if()算法,所以如果要复制符合某特定准则的元素,请使用remove_copy_if()算法 138 6如果希望在复制过程中逆转元素次序,应该使用reverse_copy() 139 7调用者必须保证目标区间有足够的空间,否则就得使用insert迭代器 140 8如果想把容器内的所有元素赋值给另一容器,应当使用assignment操作符(当两个容器的型别相同时)或者使用容器的assign()成员函数(当两个容器的型别不同时) 141 9如果希望在复制过程中删除某元素,请使用remove_copy()和remove_copy_if()算法 142 10如果希望在复制过程中改变元素,请使用transform()或replace_copy()算法 143 11时间复杂度:线性 144 145 (9)转换元素算法: 146 OutputIterator transform (InputIterator sourceBeg, InputIterator sourceEnd, OutputIterator destBeg, UnaryFunc op); 147 1针对源区间[sourceBeg, sourceEnd)中的每一个元素调用op(elem)并将结果写到以destBeg为起点的目标区间 148 2返回目标区间内最后一个被转换的元素的下一个位置,也就是第一个未被覆盖的元素的位置 149 3调用者必须保证目标区间有足够的空间,否则就得使用insert迭代器 150 4sourceBeg和destBeg可以相同,因此你可以使用这个算法来变动某一序列内的元素 151 5如果想以某值来替换符合某一标准的元素,应使用replace()算法 152 6时间复杂度:线性 153 154 OutputIterator transform (InputIterator1 source1Beg, InputIterator1 source1End, InputIterator2 source2Beg, OutputIterator destBeg, BinaryFunc op); 155 1针对第一个源区间[source1Beg, source1End)以及从source2Beg开始的第二个源区间的对应元素调用op(source1Elem, source2Elem)并将结果写到以destBeg起始的目标区间 156 2返回目标区间内最后一个被转换的元素的下一个位置,也就是第一个未被覆盖的元素的位置 157 3调用者必须保证目标区间有足够的空间,否则就得使用insert迭代器 158 4调用者必须保证第二源区间有足够空间(至少拥有和第一源区间相同的空间大小) 159 5source1Beg,source2Beg,destBeg可以相同,因此你可以让元素自己和自己结合然后将结果覆盖至某个序列 160 6时间复杂度:线性 161 162 (10)互换元素内容算法: 163 ForwardIterator2 swap_ranges (ForwardIterator1 beg1, ForwardIterator1 end1, ForwardIterator2 beg2); 164 1将区间[beg1, end1)内的元素和从beg2开始的区间内的对应元素互换 165 2返回第二区间中的最后一个被交换元素的下一位置 166 3调用者必须保证目标区间有足够空间 167 4两区间不得重叠 168 5如果要将相同型别的两个容器内的全部元素互换,应使用swap()成员函数这样通常更快 169 6时间复杂度:线性 170 171 (11)赋值算法: 172 void fill (ForwardIterator beg, ForwardIterator end, const T& newValue); 173 void fill_n (OutputIterator beg, Size num, const T& newValue); 174 1fill()将区间[beg, end)内的每一个元素都赋予新值newValue 175 2fill_n()将从beg开始的前num个元素赋予新值newValue 176 3调用者必须保证目标区间有足够的空间,否则就得使用insert迭代器 177 4时间复杂度:线性 178 179 void generate (ForwardIterator beg, ForwardIterator end, Func op); 180 void generator_n (OutputIterator beg, Size num, Func op); 181 1generate()调用op产生新值并赋给区间[beg, end)内的每一个元素 182 2generate_n()调用op产生新值并赋给以beg开始的区间内的前num个元素 183 3调用者必须保证目标区间有足够的空间,否则就得使用insert迭代器 184 4时间复杂度:线性 185 186 (12)替换元素算法: 187 void replace (ForwardIterator beg, ForwardIterator end, const T& oldValue, const T& newValue); 188 void replace_if (ForwardIterator beg, ForwardIterator end, UnaryPredicate op, const T& newValuedValue); 189 1replace()将区间[beg, end)内每一个与oldValue相等的元素替换为newValue 190 2replace_if()将区间[beg ,end)内每一个令op(elem)为true的元素替换为newValue 191 3op不应该在函数调用过程中改变自身状态 192 4时间复杂度:线性 193 194 OutputIterator replace_copy (InputIterator sourceBeg, InputIterator sourceEnd, OutputIterator destBeg, const T& oldValue, const T& newValue); 195 OutputIterator replace_copy_if (InputIterator sourceBeg, InputIterator sourceEnd, OutputIterator destBeg, UnaryPredicate op, const T& newValue); 196 1replace_copy()是copy()和replace()的组合,它将源区间[sourceBeg, sourceEnd)内的元素复制到以destBeg开始的目标区间去,同时将与oldValue相等的所有元素替换成newValue 197 2replace_copy_if()是copy()和replace_if()的组合,它将源区间[sourceBeg, sourceEnd)内的元素复制到以destBeg开始的目标区间去,同时将令op(elem)结果为true的所有元素替换成newValue 198 3俩个算法都返回目标区间内最后一个被复制的元素的下一个位置,也就是第一个未被覆盖的元素的位置 199 4op不应该在函数调用过程中改变自身状态 200 5时间复杂度:线性 201 202 (13)移除性算法: 203 ForwardIterator remove (ForwardIterator beg, ForwardIterator end, const T& value); 204 ForwardIterator remove_if (ForwardIterator beg, ForwardIterator end, UnaryPredicate op); 205 1remove()会移除区间[beg, end)中的每一个与value相等的元素 206 2remove_if()会移除区间[beg, end)中的每一个令op(elem)结果为true的元素 207 3两个算法都会返回变动后的序列的新逻辑终点(也就是最后一个未被移除元素的下一个位置) 208 4这些算法会把原来置于后面的未被移除元素向前移动,覆盖被移除元素 209 5未被移除元素在相对次序上保持不变 210 6调用者在调用此算法后,应保证从此采用返回的新逻辑终点而不再使用原始终点end 211 7op不应该在函数调用过程中改变自身状态 212 8由于会发生元素变动,所以这些算法不可用于关联式容器,关联式容器提供了功能相似的成员函数erase() 213 9list提供了一个等效成员函数remove():不是重新赋值元素,而是重新安排指针 214 10时间复杂度:线性 215 216 OutputIterator remove_copy (InputIterator sourceBeg, InputIterator sourceEnd, OutputIterator destBeg, const T& value); 217 OutputIterator remove_copy_if (InputIterator sourceBeg, InputIterator sourceEnd, OutputIterator destBeg, UnaryPredicate op); 218 1remove_copy()是copy()和remove()的组合,它将源区间[sourceBeg, sourceEnd)内的元素复制到以destBeg开始的目标区间去,同时移除与value相等的所有元素 219 2remove_copy_if()是copy()和remove_if()的组合,它将源区间[sourceBeg, sourceEnd)内的元素复制到以destBeg开始的目标区间去,同时移除令op(elem)结果为true的所有元素 220 3俩个算法都返回目标区间内最后一个被复制的元素的下一个位置,也就是第一个未被覆盖的元素的位置 221 4op不应该在函数调用过程中改变自身状态 222 5调用者必须保证目标区间有足够的空间,否则就得使用insert迭代器 223 6时间复杂度:线性 224 225 ForwardIterator unique (ForwardIterator beg, ForwardIterator end); 226 ForwardIterator unique (ForwardIterator beg, ForwardIterator end, BinaryPredicate op); 227 1两个算法都会移除连续重复元素中的多余元素 228 2第一形式将区间[beg, end)内的所有与前一个元素相等的元素移除,所以源区间必须先经过排序,才能使用这个算法 229 3第二形式将每一个“位于元素e之后并且造成op(elem ,e)结果为true”的所有elem元素移除,换言之此op并非用来将元素和其原本的前一元素比较,而是将它和未被移除的前一元素比较 230 4两种形式都返回被变动后的序列的新终点(最后一个未被移除的元素的下一个位置) 231 5两个算法将原本位置在后的未被移除元素向前移动,覆盖被移除元素 232 6未被移除元素在相对次序上保持不变 233 7调用者在调用此算法后,应保证从此采用返回的新逻辑终点而不再使用原始终点end 234 8op不应该在函数调用过程中改变自身状态 235 9由于会发生元素变动,所以这些算法不可用于关联式容器 236 10list提供了一个等效成员函数unique():不是重新赋值元素,而是重新安排指针 237 11时间复杂度:线性 238 239 OutputIterator unique_copy (InputIterator sourceBeg, InputIterator sourceEnd, OutputIterator destBeg); 240 OutputIterator unique_copy (InputIterator sourceBeg, InputIterator sourceEnd, OutputIterator destBeg, BinaryPredicate op); 241 1两种形式都是copy()和unique()的组合 242 2两者都将源区间[sourceBeg, sourceEnd)内的元素复制到以destBeg开始的目标区间去,并移除重复元素 243 3俩个算法都返回目标区间内最后一个被复制的元素的下一个位置,也就是第一个未被覆盖的元素的位置 244 4调用者必须保证目标区间有足够的空间,否则就得使用insert迭代器 245 5时间复杂度:线性 246 247 (14)变序性算法: 248 void reverse (BidirectionalIterator beg, BidirectionalIterator end); 249 OutputIterator reverse_copy (BidirectionalIterator sourceBeg, BidirectionalIterator sourceEnd, OutputIterator destBeg); 250 1reverse()将区间[beg, end)内的元素全部逆序 251 2reverse_copy()会将源区间[sourceBeg, sourceEnd)内的元素复制到以destBeg起始的目标区间,并在复制过程中颠倒安置次序 252 3reverse_copy()返回目标区间内最后一个被复制的元素的下一个位置,也就是第一个未被覆盖的元素的位置 253 4调用者必须保证目标区间有足够的空间,否则就得使用insert迭代器 254 5list提供了一个等效成员函数reverse():不是重新赋值元素,而是重新安排指针 255 6时间复杂度:线性 256 257 void rotate (ForwardIterator beg, ForwardIterator newBeg, ForwardIterator end); 258 1将区间[beg, end)内的元素进行旋转,执行后*newBeg成为新的第一元素 259 2调用者必须保证newBeg是区间[beg, end)内的一个有效位置,否则会引发未定义的行为 260 3时间复杂度:线性 261 262 void rotate_copy (ForwardIterator sourceBeg, ForwardIterator newBeg, ForwardIterator sourceEnd, OutputIterator destBeg); 263 1这是rotate()和copy()的组合 264 2将源区间[sourceBeg, sourceEnd)内的元素复制到以destBeg起始的目标区间中,同时旋转元素使*newBeg成为新的第一元素 265 3返回目标区间内最后一个被复制的元素的下一个位置 266 4调用者必须保证newBeg是区间[sourceBeg, sourceEnd)内的一个有效位置,否则会引发未定义的行为 267 5调用者必须保证目标区间有足够的空间,否则就得使用insert迭代器 268 6源区间和目标区间不可重叠 269 7时间复杂度:线性 270 271 bool next_permutation (BidirectionalIterator beg, BidirectionalIterator end); 272 bool prev_permutation (BidirectionalIterator beg, BidirectionalIterator end); 273 1next_permutation()会改变区间[beg, end)内的元素次序,使它符合“下一个排列次序” 274 2prev_permutation()会改变区间[beg, end)内的元素次序,使它符合“上一个排列次序” 275 3如果元素得以排列成“正规”次序,则两个算法都返回true。所谓正规次序,对next_permutation()而言为升序,对prev_permutation()而言为降序。因此如果要走遍所有排序,你必须先将所有元素(按升序或降序)排序,然后开始以循环方式调用prev_permutation()或next_permutation()直到算法返回false 276 4时间复杂度:线性 277 278 void random_shuffle (RandomAccessIterator beg, RandomAccessIterator end); 279 void random_shuffle (RandomAccessIterator beg, RandomAccessIterator end, RandomFunc& op); 280 1第一形式使用一个均匀分布随机数产生器来打乱区间[beg, end)内的元素次序 281 2第二形式使用op来打乱区间[beg, end)内的元素次序。算法内部会使用一个整数值来调用op:op(max),它应该返回一个大于零而小于max的随机数但不包括max自身 282 3注意op是一个non-const reference,所有你不可以将暂时数值或一般函数传进去 283 4时间复杂度:线性 284 285 BidirectionalIterator partition (BidirectionalIterator beg, BidirectionalIterator end, UnaryPredicate op); 286 BidirectionalIterator stable_partition (BidirectionalIterator beg, BidirectionalIterator end, UnaryPredicate op); 287 1两种算法将区间[beg, end)中的“造成op(elem)结果为true”的元素向前端移动 288 2两种算法都返回“令op(elem)结果为false”的第一个元素位置 289 3两者差别为无论元素是否符合给定的准则,stable_partition()会保持它们之间的相对次序 290 4你可以运用此算法根据排序准则将所有元素分割为两部分,nth_element()具有类似能力 291 5op不应该在函数调用中改变自身状态 292 6时间复杂度:partition()为线性,stable_partition()当系统有足够的内存时为线性、不足时为O(nlgn) 293 294 (15)排序算法: 295 void sort (RandomAccessIterator beg, RandomAccessIterator end); 296 void sort (RandomAccessIterator beg, RandomAccessIterator end, BinaryPredicate op); 297 void stable_sort (RandomAccessIterator beg, RandomAccessIterator end); 298 void stable_sort (RandomAccessIterator beg, RandomAccessIterator end, BinaryPredicate op); 299 1sort()和stable_sort()的上述第一形式使用operator<对区间[beg, end)内的所有元素进行排序 300 2sort()和stable_sort()的上述第二形式使用op(elem1, elem2)作为排序准则对区间[beg, end)内的所有元素进行排序 301 3op不应该在函数调用中改变自身状态 302 4sort()和stable_sort()的区别是后者保证相等元素的原本相对次序在排序后保持不变 303 5不可以对list调用这些算法,因为list不支持随机存取迭代器不过list提供了一个成员函数sort() 304 6时间复杂度:sort():O(nlgn),stable_sort()当系统有足够的内存时为O(nlgn)、不足时为O(nlgn*lgn) 305 306 void partial_sort (RandomAccessIterator beg, RandomAccessIterator sortEnd, RandomAccessIterator end); 307 void partial_sort (RandomAccessIterator beg, RandomAccessIterator sortEnd, RandomAccessIterator end, BinaryPredicate op); 308 1上述第一形式使用operator<对区间[beg, end)内的所有元素进行排序,使区间[beg, sortEnd)内的元素处于有序状态 309 2上述第二形式使用op(elem1, elem2)作为排序准则对区间[beg, end)内的所有元素进行排序,使区间[beg, sortEnd)内的元素处于有序状态 310 3op不应该在函数调用中改变自身状态 311 4和sort()不同的是partial_sort()并不对全部元素进行排序:一旦第一个元素直至sortEnd之间的所有元素都排好次序就立刻停止,不会对剩余的元素进行排序 312 5如果end和sortEnd相等,那么partial_sort()会对整个序列进行排序,平均而言其效率不及sort(),不过最差情况而言优于sort() 313 6时间复杂度:线性和O(nlgn)之间 314 315 RandomAccessIterator partial_sort_copy (InputIterator sourceBeg, InputIterator sourceEnd, RandomAccessIterator destBeg, RandomAccessIterator destEnd); 316 RandomAccessIterator partial_sort_copy (InputIterator sourceBeg, InputIterator sourceEnd, RandomAccessIterator destBeg, RandomAccessIterator destEnd, BinaryPredicate op); 317 1两者都是copy()和partial_sort()的组合 318 2它们将元素从源区间[sourceBeg, sourceEnd)复制到目标区间[destBeg, destEnd)同时排序 319 3被排序元素的数量是源区间和目标区间两者所含元素数量的最小值 320 4两者都返回目标区间内最后一个被复制的元素的下一个位置,也就是第一个未被覆盖的元素的位置 321 5时间复杂度:线性和O(nlgn)之间 322 323 void nth_element (RandomAccessIterator beg, RandomAccessIterator nth, RandomAccessIterator end); 324 void nth_element (RandomAccessIterator beg, RandomAccessIterator nth, RandomAccessIterator end, BinaryPredicate op); 325 1两种形式都对区间[beg, end)内的元素进行排序,使第n个位置上的元素就位,也就是说所有在位置n之前的元素小于等于它,所有位置在n之后的元素都大于等于它。这样你就得到了根据n位置上的元素分割开来的两个子序列,第一子序列的元素统统小于第二子序列的元素。如果你只需要n个最大或最小的元素,但不要求它们必须已序,那么这个算法就很有用。 326 2上述第一形式使用operator<作为排序准则 327 3上述第二形式使用op(elem1, elem2)作为排序准则 328 4op不应该在函数调用中改变自身状态 329 5时间复杂度:线性 330 331 (16)Heap算法: 332 void make_heap (RandomAccessIterator beg, RandomAccessIterator end); 333 void make_heap (RandomAccessIterator beg, RandomAccessIterator end, BinaryPredicate op); 334 1两种形式都将[beg, end)内的元素转化为heap 335 2第二形式将op(elem1, elem2)视为排序准则 336 3只有在多于一个元素的情况下才有必要使用这些函数来处理heap 337 4时间复杂度:线性 338 339 void push_heap (RandomAccessIterator beg, RandomAccessIterator end); 340 void push_heap (RandomAccessIterator beg, RandomAccessIterator end, BinaryPredicate op); 341 1两种形式都将end之前的最后一个元素加入原本就是个heap的[beg, end-1)区间内使整个区间[beg, end)成为一个heap 342 2第二形式将op(elem1, elem2)视为排序准则 343 3调用者必须保证进入函数时,区间[beg, end-1)内的元素原本已形成一个heap,而新元素紧跟其后 344 4时间复杂度:对数 345 346 void pop_heap (RandomAccessIterator beg, RandomAccessIterator end); 347 void pop_heap (RandomAccessIterator beg, RandomAccessIterator end, BinaryPredicate op); 348 1以上两种形式都将heap[beg, end)内的最高元素也就是第一个元素移动到最后的位置上,并将剩余区间[beg, end-1)内的元素组织起来成为一个新heap 349 2第二形式将op(elem1, elem2)视为排序准则 350 3调用者必须保证进入函数时,区间[beg, end)内的元素原本已形成一个heap,而新元素紧跟其后 351 4时间复杂度:对数 352 353 void sort_heap (RandomAccessIterator beg, RandomAccessIterator end); 354 void sort_heap (RandomAccessIterator beg, RandomAccessIterator end, BinaryPredicate op); 355 1以上两种形式都将heap[beg, end)转换为一个已序序列 356 2第二形式将op(elem1, elem2)视为排序准则 357 3此算法一结束,该区间就不再是个heap了 358 4调用者必须保证进入函数时,区间[beg, end)内的元素原本已形成一个heap,而新元素紧跟其后 359 5时间复杂度:对数 360 361 (17)搜寻元素: 362 bool binary_search (ForwardIterator beg, ForwardIterator end, const T& value); 363 bool binary_search (ForwardIterator beg, ForwardIterator end, const T& value, BinaryPredicate op); 364 1两种形式都用来判断已序区间[beg, end)中是否含有和value等值的元素 365 2第二形式将op(elem1, elem2)视为排序准则 366 3如果想获得被搜寻元素的位置,应使用lower_bound(),upper_bound()或equal_range()算法 367 4调用者必须保证进入算法之际该区间已序 368 5时间复杂度:如果搭配随机存取迭代器则为对数复杂度,否则为线性 369 370 bool includes (InputIterator1 beg, InputIterator1 end, InputIterator2 searchBeg, InputIterator2 searchEnd); 371 bool includes (InputIterator1 beg, InputIterator1 end, InputIterator2 searchBeg, InputIterator2 searchEnd, BinaryPredicate op); 372 1两种形式都用来判断已序区间[beg, end)是否包含另一个已序区间[searchBeg, searchEnd)中的每一个元素。也就是说对于[searchBeg, searchEnd)中的每一个元素,如果[beg, end)必有一个对应的相等元素那么[searchBeg, searchEnd)肯定是[beg, end)的子集 373 2第二形式将op(elem1, elem2)视为排序准则 374 3调用者必须保证在进入算法之际两区间都应该已经按照相同的排序准则排好序了 375 4时间复杂度:线性 376 377 ForwardIterator lower_bound (ForwardIterator beg, ForwardIterator end, const T& value); 378 ForwardIterator lower_bound (ForwardIterator beg, ForwardIterator end, const T& value, BinaryPredicate op); 379 380 ForwardIterator upper_bound (ForwardIterator beg, ForwardIterator end, const T& value); 381 ForwardIterator upper_bound (ForwardIterator beg, ForwardIterator end, const T& value, BinaryPredicate op); 382 1lower_bound()返回第一个“大于等于value”的元素位置,这是可插入“元素值为value”且“不破坏区间[beg, end)已序性”的第一个位置 383 2upper_bound()返回第一个“大于value”的元素位置,这是可插入“元素值为value”且“不破坏区间[beg, end)已序性”的最后一个位置 384 3如果不存在其值为value的元素,上述算法都返回end 385 4op(elem1, elem2)视为排序准则 386 5调用者必须保证在进入算法之际所有区间都应该已经按照排序准则排好序了 387 6如果要同时获得lower_bound()和upper_bound()的结果,请使用equal_range() 388 7关联式容器分别提供等效成员函数,性能更好 389 8时间复杂度:如果搭配随机存取迭代器则为对数复杂度,否则为线性 390 391 pair<ForwardIterator, ForwardIterator> equal_range (ForwardIterator beg, ForwardIterator end, const T& value); 392 pair<ForwardIterator, ForwardIterator> equal_range (ForwardIterator beg, ForwardIterator end, const T& value, BinaryPredicate op); 393 1两种形式都返回与value相等的元素所形成的区间,在此区间内插入其值为value的元素并不会破坏区间[beg, end)的已序性 394 2和下式等效:make_pair(lower_bound(……), upper_bound(……)) 395 3第二形式将op(elem1, elem2)视为排序准则 396 4调用者必须保证在进入算法之际两区间都应该已经按照相同的排序准则排好序了 397 5关联式容器分别提供等效成员函数,性能更好 398 6时间复杂度:如果搭配随机存取迭代器则为对数复杂度,否则为线性 399 400 (18)合并元素: 401 OutputIterator merge (InputIterator source1Beg, InputIterator source1End, InputIterator source2Beg, InputIterator source2End, OutputIterator destBeg); 402 OutputIterator merge (InputIterator source1Beg, InputIterator source1End, InputIterator source2Beg, InputIterator source2End, OutputIterator destBeg, BinaryPredicate op); 403 1两者都将源区间[source1Beg, source1End)和[source2Beg, source2End)内的元素合并,使得以destBeg起始的目标区间内含两个源区间的所有元素 404 2目标区间内的所有元素都将按顺序排列 405 3两者都返回目标区间内最后一个被复制的元素的下一个位置,也就是第一个未被覆盖的元素的位置 406 4第二形式将op(elem1, elem2)视为排序准则 407 5源区间没有任何变化 408 6调用者必须保证目标区间有足够的空间,否则就得使用insert迭代器 409 7list提供了一个等效成员函数merge() 410 8根据标准调用者应当确保两个源区间一开始都是已序,然而在大部分实作版本中上述算法可以将两个无序的源区间内的元素合并到一个无序的目标区间中,不过要考虑到这样的移植性 411 9目标区间和源区间不得重叠 412 10如果你要确保两个源区间中都存在的元素在目标区间中只出现一次,请使用set_union() 413 11如果你要获得同时存在于两个源区间的所有元素,请使用set_intersection() 414 12时间复杂度:线性 415 416 OutputIterator set_union (InputIterator source1Beg, InputIterator source1End, InputIterator source2Beg, InputIterator source2End, OutputIterator destBeg); 417 OutputIterator set_union (InputIterator source1Beg, InputIterator source1End, InputIterator source2Beg, InputIterator source2End, OutputIterator destBeg, BinaryPredicate op); 418 1两者都将源区间[source1Beg, source1End)和[source2Beg, source2End)内的元素合并,得到以destBeg起始的目标区间——这个区间内含的元素要不来自第一源区间,要不就来自第二源区间,或是同时来自两个区间 419 2同时出现于两个源区间内的元素在并集区间中将只出现一次。不过如果原来的某个源区间内原本就存在重复元素,则目标区间也会有重复元素,重复的个数是两个源区间内的重复个数的较大值 420 3两者都返回目标区间内最后一个被复制的元素的下一个位置,也就是第一个未被覆盖的元素的位置 421 4第二形式将op(elem1, elem2)视为排序准则 422 5源区间没有任何变化 423 6调用者应当确保两个源区间一开始都是已序 424 7调用者必须保证目标区间有足够的空间,否则就得使用insert迭代器 425 8目标区间和源区间不得重叠 426 9若想得到两个源区间的全部元素,应使用merge() 427 10时间复杂度:线性 428 11目标区间内的所有元素都按顺序排列 429 430 OutputIterator set_intersection (InputIterator source1Beg, InputIterator source1End, InputIterator source2Beg, InputIterator source2End, OutputIterator destBeg); 431 OutputIterator set_intersection (InputIterator source1Beg, InputIterator source1End, InputIterator source2Beg, InputIterator source2End, OutputIterator destBeg, BinaryPredicate op); 432 1两者都将源区间[source1Beg, source1End)和[source2Beg, source2End)内的元素合并,得到以destBeg起始的目标区间——这个区间内含的元素不但存在于第一源区间,也存在于第二源区间 433 2如果原来的某个源区间内原本就存在重复元素,则目标区间也会有重复元素,重复的个数是两个源区间内的重复个数的较小值 434 3两者都返回目标区间内最后一个被复制的元素的下一个位置,也就是第一个未被覆盖的元素的位置 435 4第二形式将op(elem1, elem2)视为排序准则 436 5源区间没有任何变化 437 6调用者应当确保两个源区间一开始都是已序 438 7调用者必须保证目标区间有足够的空间,否则就得使用insert迭代器 439 8目标区间和源区间不得重叠 440 9目标区间内的所有元素都按顺序排列 441 10时间复杂度:线性 442 443 OutputIterator set_difference (InputIterator source1Beg, InputIterator source1End, InputIterator source2Beg, InputIterator source2End, OutputIterator destBeg); 444 OutputIterator set_difference (InputIterator source1Beg, InputIterator source1End, InputIterator source2Beg, InputIterator source2End, OutputIterator destBeg, BinaryPredicate op); 445 1两者都将源区间[source1Beg, source1End)和[source2Beg, source2End)内的元素合并,得到以destBeg起始的目标区间——这个区间内含的元素只存在于第一源区间,不存在于第二源区间 446 2目标区间内的所有元素都按顺序排列 447 3如果原来的某个源区间内原本就存在重复元素,则目标区间也会有重复元素,重复的个数是第一源区间内的重复个数减去第二源区间内的相应重复个数,如果第二源区间内的重复个数大于第一源区间内的相应重复个数,则目标区间内的对应重复个数将会是零 448 4两者都返回目标区间内最后一个被复制的元素的下一个位置,也就是第一个未被覆盖的元素的位置 449 5第二形式将op(elem1, elem2)视为排序准则 450 6源区间没有任何变化 451 7调用者应当确保两个源区间一开始都是已序 452 8调用者必须保证目标区间有足够的空间,否则就得使用insert迭代器 453 9目标区间和源区间不得重叠 454 10时间复杂度:线性 455 456 OutputIterator set_symmetric_difference (InputIterator source1Beg, InputIterator source1End, InputIterator source2Beg, InputIterator source2End, OutputIterator destBeg); 457 OutputIterator set_symmetric_difference (InputIterator source1Beg, InputIterator source1End, InputIterator source2Beg, InputIterator source2End, OutputIterator destBeg, BinaryPredicate op); 458 1两者都将源区间[source1Beg, source1End)和[source2Beg, source2End)内的元素合并,得到以destBeg起始的目标区间——这个区间内含的元素或存在于第一源区间,或存在于第二源区间,但不同时存在于两个源区间 459 2目标区间内的所有元素都按顺序排列 460 3如果原来的某个源区间内原本就存在重复元素,则目标区间也会有重复元素,重复的个数是两个源区间内的对应重复元素的个数差值 461 4两者都返回目标区间内最后一个被复制的元素的下一个位置,也就是第一个未被覆盖的元素的位置 462 5第二形式将op(elem1, elem2)视为排序准则 463 6源区间没有任何变化 464 7调用者应当确保两个源区间一开始都是已序 465 8调用者必须保证目标区间有足够的空间,否则就得使用insert迭代器 466 9目标区间和源区间不得重叠 467 10时间复杂度:线性 468 469 void inplace_merge (BidirectionalIterator beg1, BidirectionalIterator end1beg2, BidirectionalIterator end2); 470 void inplace_merge (BidirectionalIterator beg1, BidirectionalIterator end1beg2, BidirectionalIterator end2, BinaryPredicate op); 471 1两者都是将已源区间[beg1, end1beg2)和[end1beg2, end2)的元素合并,使区间[beg1, end2)成为两者之总和(且形成已序) 472 2时间复杂度:内存足够为线性否则为O(nlgn) 473 474 (19)数值算法: 475 运用数值算法需要包含头文件:#include<numeric> 476 477 T accumulate (InputIterator beg, InputIterator end, T initValue); 478 T accumulate (InputIterator beg, InputIterator end, T initValue, BinaryFunc op); 479 1第一形式计算initValue和区间[beg, end)内的所有元素总和,具体地说它针对每一个元素调用initValue+=elem 480 2第二形式计算initValue和区间[beg, end)内每一个元素进行op运算的结果,具体地说它针对每一个元素调用initValue=op(initValue, elem) 481 3如果序列为空则两者都返回initValue 482 4时间复杂度:线性 483 484 T inner_product (InputIterator1 beg1, InputIterator1 end1,InputIterator2 beg2, T initValue); 485 T inner_product (InputIterator1 beg1, InputIterator1 end1,InputIterator2 beg2, T initValue, BinaryFunc op1, BinaryFunc op2); 486 1第一形式计算并返回[beg1, end1)区间和以beg2为起始的区间的对应元素组(再加上initValue)的内积。具体地说针对两区间内的每一组对应元素调用initValue=initValue+elem1*elem2 487 2第二形式将[beg1, end1)区间和以beg2为起始的区间的对应元素组进行op2运算再和initValue进行op1运算并将结果返回。具体地说针对两区间内的每一组对应元素调用initValue=op1(initValue, op2(elem1, elem2)) 488 3如果第一区间为空则两者都返回initValue 489 4调用者必须保证以beg2为起始的区间内含足够元素空间 490 5op1和op2都不得变动其参数内容 491 6时间复杂度:线性 492 493 OutputIterator partial_sum (InputIterator sourceBeg, InputIterator sourceEnd, OutputIterator destBeg); 494 OutputIterator partial_sum (InputIterator sourceBeg, InputIterator sourceEnd, OutputIterator destBeg, BinaryFunc op); 495 1第一形式计算源区间[sourceBeg, sourceEnd)中的每个元素的部分和,然后将结果写入以destBeg为起始的区间 496 2第二形式计算源区间[sourceBeg, sourceEnd)中的每个元素和其先前所有元素进行op运算,然后将结果写入以destBeg为起始的区间 497 3对于数列a1 a2 a3 ……它们分别计算a1, a1+a2, a1+a2+a3,……和a1, a1 op a2, a1 op a2 op a3,…… 498 4 两者都返回目标区间内最后一个被复制的元素的下一个位置,也就是第一个未被覆盖的元素的位置 499 5第一形式相当于把一个相对值序列转换为一个绝对值序列,就此而言partial_sum()正好和adjacent_difference()互补 500 6源区间和目标区间可以相同 501 7调用者必须保证目标区间有足够的空间,否则就得使用insert迭代器 502 8op不得变动其参数内容 503 9时间复杂度:线性 504 505 OutputIterator adjacent_difference (InputIterator sourceBeg, InputIterator sourceEnd, OutputIterator destBeg); 506 OutputIterator adjacent_difference (InputIterator sourceBeg, InputIterator sourceEnd, OutputIterator destBeg, BinaryFunc op); 507 1第一形式计算源区间[sourceBeg, sourceEnd)中的每个元素和其紧邻前驱元素的差值,然后将结果写入以destBeg为起始的区间 508 2第二形式计算源区间[sourceBeg, sourceEnd)中的每个元素和其紧邻前驱元素进行op运算,然后将结果写入以destBeg为起始的区间 509 3第一个元素只是被很单纯的加以复制 510 4对于数列a1 a2 a3 a4……它们分别计算a1, a2-a1, a3-a2,a4-a3, ……和a1, a2 op a1, a3 op a2, a4 op a3,…… 511 5 两者都返回目标区间内最后一个被复制的元素的下一个位置,也就是第一个未被覆盖的元素的位置 512 6第一形式相当于把一个绝对值序列转换为一个相对值序列,就此而言partial_sum()正好和adjacent_difference()互补 513 7源区间和目标区间可以相同 514 8调用者必须保证目标区间有足够的空间,否则就得使用insert迭代器 515 9op不得变动其参数内容 516 10时间复杂度:线性