// STL算法.cpp : 定义控制台应用程序的入口点。 //最后修改时间:2018/02/13,测试平台 vs2017 /* STL六个部分 容器:见相关工程,学习上有两个难点:双端队列的实现细节,RBtree实现细节 分配器:allocator,学习版本是侯捷的书,sgi新版本增了继承层次。内存学习的高级主题 算法:本工程,容器无关的算法 适配器:容器/仿函数。基于容器实现的栈,单链表等 迭代器:最好是参考网站内容http://zh.cppreference.com/w/cpp/iterator 仿函数:无对应工程,比较简单,熟悉已有的小函数可以省得造轮子。 */ //本页完成的是 3.算法。部分C++17的例子尚未提供 //泛型算法及相关辅助函数 #include "stdafx.h" #include <iterator> #include <iostream> #include <string> #include <vector> #include <algorithm> #include <functional> #include <numeric> #include <list> #include <iterator> #include <experimental\filesystem> #include <array> #include <functional> #include <thread> #include <chrono> #include <cctype> #include <random> #include <forward_list> #include <cstdlib> #include <climits> using namespace std; template<typename Container> bool in_quote(const Container& cont, const std::string& s) { return std::search(cont.begin(), cont.end(), s.begin(), s.end()) != cont.end(); } template <class Container, class Size, class T> bool consecutive_values(const Container& c, Size count, const T& v) { return std::search_n(std::begin(c), std::end(c), count, v) != std::end(c); } template<class ForwardIt> void selection_sort(ForwardIt begin, ForwardIt end) { for (ForwardIt i = begin; i != end; ++i) std::iter_swap(i, std::min_element(i, end)); } template <class ForwardIt> void quicksort(ForwardIt first, ForwardIt last) { if (first == last) return; auto pivot = *std::next(first, std::distance(first, last) / 2); ForwardIt middle1 = std::partition(first, last, [pivot](const auto& em) { return em < pivot; }); ForwardIt middle2 = std::partition(middle1, last, [pivot](const auto& em) { return !(pivot < em); }); quicksort(first, middle1); quicksort(middle2, last); } template<class ForwardIt, class T, class Compare = std::less<>> ForwardIt binary_find(ForwardIt first, ForwardIt last, const T& value, Compare comp = {}) { // 注意:类型 T 和 Forward 解引用后的类型都必须可隐式转换为 // 用于 Compare 的 Type1 和 Type2 。 // 这严格于 lower_bound 要求(见上述) first = std::lower_bound(first, last, value, comp); return first != last && !comp(value, *first) ? first : last; } template<class Iter> void merge_sort(Iter first, Iter last) { if (last - first > 1) { Iter middle = first + (last - first) / 2; merge_sort(first, middle); merge_sort(middle, last); std::inplace_merge(first, middle, last); } } //例子全部来源于cppreference int main() { /*泛型算法,超过100个,分为 *只读算法 *写容器算法 *重排算法 */ //////////////////////////////////////// //只读算法///////////////////////////// //////////////////////////////////////// { //any_of,all_of,none_of //检查一定范围之内,是否全部、存在或不存在元素使得谓词为true { std::vector<int,allocator<int>> v(10, 2); std::partial_sum(v.cbegin(), v.cend(), v.begin());//2,4,6....20 std::cout << "Among the numbers: "; std::copy(v.cbegin(), v.cend(), std::ostream_iterator<int>(std::cout, " ")); std::cout << ‘\n‘; if (std::all_of(v.cbegin(), v.cend(), [](int i) { return i % 2 == 0; })) { std::cout << "All numbers are even\n"; } if (std::none_of(v.cbegin(), v.cend(), std::bind(std::modulus<int>(), std::placeholders::_1, 2))) { std::cout << "None of them are odd\n"; } struct DivisibleBy { const int d; DivisibleBy(int n) : d(n) {} bool operator()(int n) const { return n % d == 0; } }; if (std::any_of(v.cbegin(), v.cend(), DivisibleBy(7))) { std::cout << "At least one number is divisible by 7\n"; } } //for_each将一个函数应用于某一范围的元素 //返回值是参数3,可执行函数std::move(f) { std::vector<int> nums{ 3, 4, 2, 8, 15, 267 }; auto print = [](const int& n) { std::cout << " " << n; }; std::cout << "before:"; std::for_each(nums.begin(), nums.end(), print); std::cout << ‘\n‘; std::for_each(nums.begin(), nums.end(), [](int &n) { n++; }); // 对每个数调用 Sum::operator() struct Sum { Sum() : sum{ 0 } { } void operator()(int n) { sum += n; } int sum; }; Sum s = std::for_each(nums.begin(), nums.end(), Sum()); std::cout << "after: "; std::for_each(nums.begin(), nums.end(), print); std::cout << ‘\n‘; std::cout << "sum: " << s.sum << ‘\n‘; } //for_each_n应用函数对象到序列的首 n 个元素 //count //count_if { std::vector<int> v{ 1, 2, 3, 4, 4, 3, 7, 8, 9, 10 }; // 确定 std::vector 中有多少个整数匹配目标值。 int target1 = 3; int target2 = 5; int num_items1 = std::count(v.begin(), v.end(), target1); int num_items2 = std::count(v.begin(), v.end(), target2); std::cout << "number: " << target1 << " count: " << num_items1 << ‘\n‘; std::cout << "number: " << target2 << " count: " << num_items2 << ‘\n‘; // 用 lambda 表达式计量能被 3 整除的元素数。 int num_items3 = std::count_if(v.begin(), v.end(), [](int i) {return i % 3 == 0; }); std::cout << "number divisible by three: " << num_items3 << ‘\n‘; } //mismatch查找两个范围第一个不同元素的位置 //返回值是两个迭代器std::make_pair(first1, first2); { auto mirror_ends=[](const std::string& in) { return std::string(in.begin(), std::mismatch(in.begin(), in.end(), in.rbegin()).first); }; std::cout << mirror_ends("abXYZba") << ‘\n‘//ab << mirror_ends("abca") << ‘\n‘//a << mirror_ends("aba") << ‘\n‘;//aba } //find //find_if //find_if_not { int n1 = 3; int n2 = 5; std::vector<int> v{ 0, 1, 2, 3, 4 }; auto result1 = std::find(std::begin(v), std::end(v), n1); auto result2 = std::find(std::begin(v), std::end(v), n2); if (result1 != std::end(v)) { std::cout << "v contains: " << n1 << ‘\n‘; } else { std::cout << "v does not contain: " << n1 << ‘\n‘; } if (result2 != std::end(v)) { std::cout << "v contains: " << n2 << ‘\n‘; } else { std::cout << "v does not contain: " << n2 << ‘\n‘; } } //find_end查找一定范围内最后出现的元素序列 //下列代码用 find_end() 搜索二个不同的数列 { std::vector<int> v{ 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4 }; std::vector<int>::iterator result; std::vector<int> t1{ 1, 2, 3 }; result = std::find_end(v.begin(), v.end(), t1.begin(), t1.end()); if (result == v.end()) { std::cout << "subsequence not found\n"; } else { std::cout << "last subsequence is at: " << std::distance(v.begin(), result) << "\n"; } std::vector<int> t2{ 4, 5, 6 }; result = std::find_end(v.begin(), v.end(), t2.begin(), t2.end()); if (result == v.end()) { std::cout << "subsequence not found\n"; } else { std::cout << "last subsequence is at: " << std::distance(v.begin(), result) << "\n"; } } //find_first_of查找元素集合中的任意元素 { std::vector<int> v{ 0, 2, 3, 25, 5 }; std::vector<int> t{ 3, 19, 10, 2 }; auto result = std::find_first_of(v.begin(), v.end(), t.begin(), t.end()); if (result == v.end()) { std::cout << "no elements of v were equal to 3, 19, 10 or 2\n"; } else { std::cout << "found a match at " << std::distance(v.begin(), result) << "\n"; } } //adjacent_find查找彼此相邻的两个相同(或其它的关系)的元素 { std::vector<int> v1{ 0, 1, 2, 3, 40, 40, 41, 41, 5 }; auto i1 = std::adjacent_find(v1.begin(), v1.end()); if (i1 == v1.end()) { std::cout << "no matching adjacent elements\n"; } else { std::cout << "the first adjacent pair of equal elements at: " << std::distance(v1.begin(), i1) << ‘\n‘; } auto i2 = std::adjacent_find(v1.begin(), v1.end(), std::greater<int>()); if (i2 == v1.end()) { std::cout << "The entire vector is sorted in ascending order\n"; } else { std::cout << "The last element in the non-decreasing subsequence is at: " << std::distance(v1.begin(), i2) << ‘\n‘; } /* The first adjacent pair of equal elements at : 4 The last element in the non - decreasing subsequence is at : 7 */ } //search查找一个元素区间 { std::string str = "why waste time learning, when ignorance is instantaneous?"; // str.find() 也能使用 std::cout << std::boolalpha << in_quote(str, "learning") << ‘\n‘ << in_quote(str, "lemming") << ‘\n‘; std::vector<char> vec(str.begin(), str.end()); std::cout << std::boolalpha << in_quote(vec, "learning") << ‘\n‘ << in_quote(vec, "lemming") << ‘\n‘; } //search_n { const char sequence[] = "1001010100010101001010101"; std::cout << std::boolalpha; std::cout << "Has 4 consecutive zeros: " << consecutive_values(sequence, 4, ‘0‘) << ‘\n‘; std::cout << "Has 3 consecutive zeros: " << consecutive_values(sequence, 3, ‘0‘) << ‘\n‘; } } //写容器/修改容器算法 { //copy //copy_if { std::vector<int> from_vector(10); std::iota(from_vector.begin(), from_vector.end(), 0); std::vector<int> to_vector; std::copy(from_vector.begin(), from_vector.end(), std::back_inserter(to_vector)); // 或可选地, // std::vector<int> to_vector(from_vector.size()); // std::copy(from_vector.begin(), from_vector.end(), to_vector.begin()); // 任一方式都等价于 // std::vector<int> to_vector = from_vector; std::cout << "to_vector contains: "; std::copy(to_vector.begin(), to_vector.end(), std::ostream_iterator<int>(std::cout, " ")); std::cout << ‘\n‘; } //copy_n复制一定数目的元素到新的位置 { std::string in = "1234567890"; std::string out; std::copy_n(in.begin(), 4, std::back_inserter(out)); std::cout << out << ‘\n‘; } //copy_backward按从后往前的顺序复制一个范围内的元素 //要求BidirectionalIterator { std::vector<int> from_vector; for (int i = 0; i < 10; i++) { from_vector.push_back(i); } std::vector<int> to_vector(15); std::copy_backward(from_vector.begin(), from_vector.end(), to_vector.end()); std::cout << "to_vector contains: "; for (auto i : to_vector) { std::cout << i << " ";//0 0 0 0 0 0 1 2 3 4 5 6 7 8 9 } } //move { auto f=[](int n) { std::this_thread::sleep_for(std::chrono::seconds(n)); std::cout << "thread " << n << " ended" << ‘\n‘; }; std::vector<std::thread> v; v.emplace_back(f, 1); v.emplace_back(f, 2); v.emplace_back(f, 3); std::list<std::thread> l; // copy() 无法编译,因为 std::thread 不可复制 std::move(v.begin(), v.end(), std::back_inserter(l)); for (auto& t : l) t.join(); } //move_backward { std::vector<std::string> src{ "foo", "bar", "baz" }; std::vector<std::string> dest(src.size()); std::cout << "src: "; for (const auto &s : src) std::cout << s << ‘ ‘; std::cout << "\ndest: "; for (const auto &s : dest) std::cout << s << ‘ ‘; std::cout << ‘\n‘; std::move_backward(src.begin(), src.end(), dest.end()); std::cout << "src: "; for (const auto &s : src) std::cout << s << ‘ ‘; std::cout << "\ndest: "; for (const auto &s : dest) std::cout << s << ‘ ‘; std::cout << ‘\n‘; } //fill { std::vector<int> v{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; std::fill(v.begin(), v.end(), -1); for (auto elem : v) { std::cout << elem << " "; } std::cout << "\n"; } //fill_n基本同上 //transform将一个函数应用于某一范围的元素 //和for_each不同的是,它需要指定输出迭代器,且支持2个操作数 { std::string s("hello"); std::transform(s.begin(), s.end(), s.begin(), [](unsigned char c) -> unsigned char { return std::toupper(c); });//#include <cctype> std::vector<std::size_t> ordinals; std::transform(s.begin(), s.end(), std::back_inserter(ordinals), [](unsigned char c) -> std::size_t { return c; }); std::cout << s << ‘:‘; for (auto ord : ordinals) { std::cout << ‘ ‘ << ord; } } //generate { std::vector<int> v(5); std::generate(v.begin(), v.end(), [n = 0]() mutable { return n++; }); std::cout << "v: "; for (auto iv : v) { std::cout << iv << " "; } std::cout << "\n"; } //generate_n几乎同上 //remove //remove_if { std::string str1 = "Text with some spaces"; str1.erase(std::remove(str1.begin(), str1.end(), ‘ ‘), str1.end()); std::cout << str1 << ‘\n‘; std::string str2 = "Text\n with\tsome \t whitespaces\n\n"; str2.erase(std::remove_if(str2.begin(), str2.end(), [](unsigned char x) {return std::isspace(x); }), str2.end()); std::cout << str2 << ‘\n‘; } //remove_copy //remove_copy_if { std::string str = "Text with some spaces"; std::cout << "before: " << str << "\n"; std::cout << "after: "; std::remove_copy(str.begin(), str.end(), std::ostream_iterator<char>(std::cout), ‘ ‘); std::cout << ‘\n‘; } //replace //replace_if { std::array<int, 10> s{ 5, 7, 4, 2, 8, 6, 1, 9, 0, 3 }; std::replace(s.begin(), s.end(), 8, 88); for (int a : s) { std::cout << a << " ";//5 7 4 2 88 6 1 9 0 3 } std::cout << ‘\n‘; std::replace_if(s.begin(), s.end(), std::bind(std::less<int>(), std::placeholders::_1, 5), 55); for (int a : s) { std::cout << a << " ";//5 7 55 55 88 6 55 9 55 55 } std::cout << ‘\n‘; } //replace_copy //replace_copy_if { std::vector<int> v{ 5, 7, 4, 2, 8, 6, 1, 9, 0, 3 }; std::replace_copy_if(v.begin(), v.end(), std::ostream_iterator<int>(std::cout, " "), [](int n) {return n > 5; }, 99); std::cout << ‘\n‘; } //swap //swap_ranges { std::vector<int> v = { 1, 2, 3, 4, 5 }; std::list<int> l = { -1, -2, -3, -4, -5 }; std::swap_ranges(v.begin(), v.begin() + 3, l.begin()); for (int n : v) std::cout << n << ‘ ‘;//-1 -2 -3 4 5 std::cout << ‘\n‘; for (int n : l) std::cout << n << ‘ ‘;//1 2 3 -4 -5 std::cout << ‘\n‘; } //iter_swap交换给定的迭代器所指向的元素的值。 { std::random_device rd; std::mt19937 gen(rd()); std::uniform_int_distribution<> dist(-10, 10); std::vector<int> v; generate_n(back_inserter(v), 20, bind(dist, gen)); std::cout << "Before sort: "; copy(v.begin(), v.end(), std::ostream_iterator<int>(std::cout, " ")); selection_sort(v.begin(), v.end()); std::cout << "\nAfter sort: "; copy(v.begin(), v.end(), std::ostream_iterator<int>(std::cout, " ")); std::cout << ‘\n‘; } //reverse { std::vector<int> v{ 1,2,3 }; std::reverse(std::begin(v), std::end(v)); for (auto e : v) std::cout << e; std::cout << ‘\n‘; int a[] = { 4, 5, 6, 7 }; std::reverse(std::begin(a), std::end(a)); for (auto e : a) std::cout << e; } //reverse_copy { std::vector<int> v({ 1,2,3 }); for (const auto& value : v) { std::cout << value << " "; } std::cout << ‘\n‘; std::vector<int> destination(3); std::reverse_copy(std::begin(v), std::end(v), std::begin(destination)); for (const auto& value : destination) { std::cout << value << " "; } std::cout << ‘\n‘; } //rotate将区间内的元素旋转 { std::vector<int> v{ 2, 4, 2, 0, 5, 10, 7, 3, 7, 1 }; std::cout << "before sort: "; for (int n : v) std::cout << n << ‘ ‘; std::cout << ‘\n‘; //2 4 2 0 5 10 7 3 7 1 // 插入排序 for (auto i = v.begin(); i != v.end(); ++i) { std::rotate(std::upper_bound(v.begin(), i, *i), i, i + 1); } std::cout << "after sort: "; for (int n : v) std::cout << n << ‘ ‘; std::cout << ‘\n‘;//0 1 2 2 3 4 5 7 7 10 // 简单地旋转到左侧 std::rotate(v.begin(), v.begin() + 1, v.end()); std::cout << "simple rotate left : "; for (int n : v) std::cout << n << ‘ ‘; std::cout << ‘\n‘;//1 2 2 3 4 5 7 7 10 0 // 简单地旋转到右侧 std::rotate(v.rbegin(), v.rbegin() + 1, v.rend()); std::cout << "simple rotate right : "; for (int n : v) std::cout << n << ‘ ‘; std::cout << ‘\n‘;//0 1 2 2 3 4 5 7 7 10 } //rotate_copy //random_shuffle将范围内的元素随机重新排序 { std::vector<int> v = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; std::random_device rd; std::mt19937 g(rd()); std::shuffle(v.begin(), v.end(), g); std::copy(v.begin(), v.end(), std::ostream_iterator<int>(std::cout, " ")); std::cout << "\n"; } //sample,C++17 //unique删除区间内连续重复的元素 { // 移除重复元素(正常使用) std::vector<int> v{ 1,2,3,1,2,3,3,4,5,4,5,6,7 }; std::sort(v.begin(), v.end()); // 1 1 2 2 3 3 3 4 4 5 5 6 7 auto last = std::unique(v.begin(), v.end()); // v 现在保有 {1 2 3 4 5 6 7 x x x x x x} ,其中 ‘x‘ 为不确定 v.erase(last, v.end()); for (int i : v) std::cout << i << " "; std::cout << "\n"; // 移除连续空格 std::string s = "wanna go to space?"; auto end = std::unique(s.begin(), s.end(), [](char l, char r) { return std::isspace(l) && std::isspace(r) && l == r; }); // s 现在保有 "wanna go to space?xxxxxxxx" ,其中 ‘x‘ 为不确定 std::cout << std::string(s.begin(), end) << ‘\n‘; } //unique_copy } //划分操作 { //is_partitioned判断区间是否被给定的谓词划分 { std::array<int, 9> v = { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; auto is_even = [](int i) { return i % 2 == 0; }; std::cout.setf(std::ios_base::boolalpha); std::cout << std::is_partitioned(v.begin(), v.end(), is_even) << ‘ ‘; std::partition(v.begin(), v.end(), is_even); std::cout << std::is_partitioned(v.begin(), v.end(), is_even) << ‘ ‘; std::reverse(v.begin(), v.end()); std::cout << std::is_partitioned(v.begin(), v.end(), is_even); //false true false } //partition把一个区间的元素分为两组 { std::vector<int> v = { 0,1,2,3,4,5,6,7,8,9 }; std::cout << "Original vector:\n "; for (int elem : v) std::cout << elem << ‘ ‘; auto it = std::partition(v.begin(), v.end(), [](int i) {return i % 2 == 0; }); std::cout << "\nPartitioned vector:\n "; std::copy(std::begin(v), it, std::ostream_iterator<int>(std::cout, " ")); std::cout << " * "; std::copy(it, std::end(v), std::ostream_iterator<int>(std::cout, " ")); std::forward_list<int> fl = { 1, 30, -4, 3, 5, -4, 1, 6, -8, 2, -5, 64, 1, 92 }; std::cout << "\nUnsorted list:\n "; for (int n : fl) std::cout << n << ‘ ‘; std::cout << ‘\n‘; quicksort(std::begin(fl), std::end(fl)); std::cout << "Sorted using quicksort:\n "; for (int fi : fl) std::cout << fi << ‘ ‘; std::cout << ‘\n‘; } //partition_copy { int arr[10] = { 1,2,3,4,5,6,7,8,9,10 }; int true_arr[5] = { 0 }; int false_arr[5] = { 0 }; std::partition_copy(std::begin(arr), std::end(arr), std::begin(true_arr), std::begin(false_arr), [](int i) {return i > 5; }); std::cout << "true_arr: "; for (auto it = std::begin(true_arr); it != std::end(true_arr); ++it) { std::cout << *it << ‘ ‘; } std::cout << ‘\n‘; std::cout << "false_arr: "; for (auto it = std::begin(false_arr); it != std::end(false_arr); ++it) { std::cout << *it << ‘ ‘; } std::cout << ‘\n‘; } //stable_partition将元素分为两组,同时保留其相对顺序 { std::vector<int> v{ 0, 0, 3, 0, 2, 4, 5, 0, 7 }; std::stable_partition(v.begin(), v.end(), [](int n) {return n>0; }); for (int n : v) { std::cout << n << ‘ ‘; } std::cout << ‘\n‘; } //partition_point { std::array<int, 9> v = { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; auto is_even = [](int i) { return i % 2 == 0; }; std::partition(v.begin(), v.end(), is_even); auto p = std::partition_point(v.begin(), v.end(), is_even); std::cout << "Before partition:\n "; std::copy(v.begin(), p, std::ostream_iterator<int>(std::cout, " ")); std::cout << "\nAfter partition:\n "; std::copy(p, v.end(), std::ostream_iterator<int>(std::cout, " ")); } } //排序操作 { //is_sorted /* template<class ForwardIt, class Compare> bool is_sorted(ForwardIt first, ForwardIt last, Compare comp) { return std::is_sorted_until(first, last, comp) == last; } */ { int digits[] = { 3, 1, 4, 1, 5 }; for (auto i : digits) std::cout << i << ‘ ‘; std::cout << ": is_sorted: " << std::boolalpha << std::is_sorted(std::begin(digits), std::end(digits)) << ‘\n‘; std::sort(std::begin(digits), std::end(digits)); for (auto i : digits) std::cout << i << ‘ ‘; std::cout << ": is_sorted: " << std::is_sorted(std::begin(digits), std::end(digits)) << ‘\n‘; } //is_sorted_until找出最大的已排序子范围 { std::random_device rd; std::mt19937 g(rd()); const int N = 6; int nums[N] = { 3, 1, 4, 1, 5, 9 }; const int min_sorted_size = 4; int sorted_size = 0; do { std::shuffle(nums, nums + N, g); int *sorted_end = std::is_sorted_until(nums, nums + N); sorted_size = std::distance(nums, sorted_end); for (auto i : nums) std::cout << i << ‘ ‘; std::cout << " : " << sorted_size << " initial sorted elements\n"; } while (sorted_size < min_sorted_size); } //sort { std::array<int, 10> s = { 5, 7, 4, 2, 8, 6, 1, 9, 0, 3 }; // 用默认的 operator< 排序 std::sort(s.begin(), s.end()); for (auto a : s) { std::cout << a << " "; } std::cout << ‘\n‘; // 用标准库比较函数对象排序 std::sort(s.begin(), s.end(), std::greater<int>()); for (auto a : s) { std::cout << a << " "; } std::cout << ‘\n‘; // 用自定义函数对象排序 struct { bool operator()(int a, int b) const { return a < b; } } customLess; std::sort(s.begin(), s.end(), customLess); for (auto a : s) { std::cout << a << " "; } std::cout << ‘\n‘; // 用 lambda 表达式排序 std::sort(s.begin(), s.end(), [](int a, int b) { return b < a; }); for (auto a : s) { std::cout << a << " "; } std::cout << ‘\n‘; } //partial_sort { std::array<int, 10> s{ 5, 7, 4, 2, 8, 6, 1, 9, 0, 3 }; std::partial_sort(s.begin(), s.begin() + 3, s.end()); for (int a : s) { std::cout << a << " "; } } //partial_sort_copy对区间内的元素进行复制并部分排序 { std::vector<int> v0{ 4, 2, 5, 1, 3 }; std::vector<int> v1{ 10, 11, 12 }; std::vector<int> v2{ 10, 11, 12, 13, 14, 15, 16 }; std::vector<int>::iterator it; it = std::partial_sort_copy(v0.begin(), v0.end(), v1.begin(), v1.end()); std::cout << "Writing to the smaller vector in ascending order gives: "; for (int a : v1) { std::cout << a << " ";// 1 2 3 } std::cout << ‘\n‘; if (it == v1.end()) std::cout << "The return value is the end iterator\n"; it = std::partial_sort_copy(v0.begin(), v0.end(), v2.begin(), v2.end(), std::greater<int>()); std::cout << "Writing to the larger vector in descending order gives: "; for (int a : v2) { std::cout << a << " ";//5 4 3 2 1 15 16 } std::cout << ‘\n‘ << "The return value is the iterator to " << *it << ‘\n‘;//15 } //stable_sort { struct Employee { Employee(int age, std::string name) : age(age), name(name) { } int age; std::string name; // 不参与比较 }; std::vector<Employee> v = { Employee(108, "Zaphod"), Employee(32, "Arthur"), Employee(108, "Ford"), }; std::stable_sort(v.begin(), v.end(), [](const Employee &lhs, const Employee &rhs) { return lhs.age < rhs.age; }); for (const Employee &e : v) { std::cout << e.age << ", " << e.name << ‘\n‘; } } //nth_element将给定的区间部分排序,确保区间被给定的元素划分 /* nth_element 是部分排序算法,它重排 [first, last) 中元素,使得: nth 所指向的元素被更改为假如 {tt|[first, last)}} 已排序则该位置会出现的元素。 这个新的 nth 元素前的所有元素小于或等于新的 nth 元素后的所有元素。 */ { std::vector<int> v{ 5, 6, 4, 3, 2, 6, 7, 9, 3 }; std::nth_element(v.begin(), v.begin() + v.size() / 2, v.end()); std::cout << "The median is " << v[v.size() / 2] << ‘\n‘; std::nth_element(v.begin(), v.begin() + 1, v.end(), std::greater<int>()); std::cout << "The second largest element is " << v[1] << ‘\n‘; // //The median is 5 //The second largest element is 7 } } //二分搜索,针对已排序序列 { //lower_bound //upper_bound { std::vector<int> data = { 1, 1, 2, 3, 3, 3, 3, 4, 4, 4, 5, 5, 6 }; //第一个不小于4的iter auto lower = std::lower_bound(data.begin(), data.end(), 4); //第一个大于4的iter auto upper = std::upper_bound(data.begin(), data.end(), 4); std::copy(lower, upper, std::ostream_iterator<int>(std::cout, " "));//444 std::cout << ‘\n‘; // 经典二分搜索,仅若存在才返回值 data = { 1, 2, 4, 6, 9, 10 }; auto it = binary_find(data.cbegin(), data.cend(), 4); // 选择 ‘5‘ 的 < 将返回 end() if (it != data.cend()) //4 found at index 2 std::cout << *it << " found at index " << std::distance(data.cbegin(), it); } //binary_search { std::vector<int> haystack{ 1, 3, 4, 5, 9 }; std::vector<int> needles{ 1, 2, 3 }; for (auto needle : needles) { std::cout << "Searching for " << needle << ‘\n‘; if (std::binary_search(haystack.begin(), haystack.end(), needle)) { std::cout << "Found " << needle << ‘\n‘; } else { std::cout << "no dice!\n"; } } } //equal_range { struct S { int number; char name; // 注意:此比较运算符忽略 name bool operator< (const S& s) const { return number < s.number; } }; std::vector<S> vec = { { 1,‘A‘ },{ 2,‘B‘ },{ 2,‘C‘ },{ 2,‘D‘ },{ 4,‘G‘ },{ 3,‘F‘ } }; S value = { 2, ‘?‘ }; auto p = std::equal_range(vec.begin(), vec.end(), value); for (auto i = p.first; i != p.second; ++i) std::cout << i->name << ‘ ‘; // 异相比较: struct Comp { bool operator() (const S& s, int i) const { return s.number < i; } bool operator() (int i, const S& s) const { return i < s.number; } }; auto p2 = std::equal_range(vec.begin(), vec.end(), 2, Comp{}); for (auto i = p2.first; i != p2.second; ++i) std::cout << i->name << ‘ ‘; //B C D B C D } } //集合操作 { //merge { std::random_device rd; std::mt19937 mt(rd()); std::uniform_int_distribution<> dis(0, 9); std::vector<int> v1(10), v2(10); std::generate(v1.begin(), v1.end(), std::bind(dis, std::ref(mt))); std::generate(v2.begin(), v2.end(), std::bind(dis, std::ref(mt))); // 排序 std::sort(v1.begin(), v1.end()); std::sort(v2.begin(), v2.end()); // 输出 v1 std::cout << "v1 : "; std::copy(v1.begin(), v1.end(), std::ostream_iterator<int>(std::cout, " ")); std::cout << ‘\n‘; // 输出 v2 std::cout << "v2 : "; std::copy(v2.begin(), v2.end(), std::ostream_iterator<int>(std::cout, " ")); std::cout << ‘\n‘; // 归并 std::vector<int> dst; std::merge(v1.begin(), v1.end(), v2.begin(), v2.end(), std::back_inserter(dst)); // 输出 std::cout << "dst: "; std::copy(dst.begin(), dst.end(), std::ostream_iterator<int>(std::cout, " ")); std::cout << ‘\n‘; } //inplace_merge 就地合并两个有序的区间,注意是有序 //有点复杂,需要再看一遍,此函数试图分配临时缓冲区。若分配失败,则选择较低效的算法。 //交换值即可,为什么参考上说要分配缓冲区? { std::vector<int> v{ 8, 2, -2, 0, 11, 11, 1, 7, 3 }; merge_sort(v.begin(), v.end()); for (auto n : v) { std::cout << n << ‘ ‘; } std::cout << ‘\n‘; } //includes如果一个集合是另外一个集合的子集则返回true { std::vector<char> v1{ ‘a‘, ‘b‘, ‘c‘, ‘f‘, ‘h‘, ‘x‘ }; std::vector<char> v2{ ‘a‘, ‘b‘, ‘c‘ }; std::vector<char> v3{ ‘a‘, ‘c‘ }; std::vector<char> v4{ ‘g‘ }; std::vector<char> v5{ ‘a‘, ‘c‘, ‘g‘ }; for (auto i : v1) std::cout << i << ‘ ‘; std::cout << "\nincludes:\n" << std::boolalpha; for (auto i : v2) std::cout << i << ‘ ‘; std::cout << ": " << std::includes(v1.begin(), v1.end(), v2.begin(), v2.end()) << ‘\n‘; for (auto i : v3) std::cout << i << ‘ ‘; std::cout << ": " << std::includes(v1.begin(), v1.end(), v3.begin(), v3.end()) << ‘\n‘; for (auto i : v4) std::cout << i << ‘ ‘; std::cout << ": " << std::includes(v1.begin(), v1.end(), v4.begin(), v4.end()) << ‘\n‘; for (auto i : v5) std::cout << i << ‘ ‘; std::cout << ": " << std::includes(v1.begin(), v1.end(), v5.begin(), v5.end()) << ‘\n‘; auto cmp_nocase = [](char a, char b) { return std::tolower(a) < std::tolower(b); }; std::vector<char> v6{ ‘A‘, ‘B‘, ‘C‘ }; for (auto i : v6) std::cout << i << ‘ ‘; std::cout << ": (case-insensitive) " << std::includes(v1.begin(), v1.end(), v6.begin(), v6.end(), cmp_nocase) << ‘\n‘; } //set_difference计算两个集合的差集 { std::vector<int> v1{ 1, 2, 5, 5, 5, 9 }; std::vector<int> v2{ 2, 5, 7 }; std::vector<int> diff; std::set_difference(v1.begin(), v1.end(), v2.begin(), v2.end(), std::inserter(diff, diff.begin())); for (auto i : v1) std::cout << i << ‘ ‘; std::cout << "minus "; for (auto i : v2) std::cout << i << ‘ ‘; std::cout << "is: "; for (auto i : diff) std::cout << i << ‘ ‘; std::cout << ‘\n‘; } //set_intersection计算两个集合的交集 { std::vector<int> v1{ 1,2,3,4,5,6,7,8 }; std::vector<int> v2{ 5, 7, 9,10 }; std::sort(v1.begin(), v1.end()); std::sort(v2.begin(), v2.end()); std::vector<int> v_intersection; std::set_intersection(v1.begin(), v1.end(), v2.begin(), v2.end(), std::back_inserter(v_intersection)); for (int n : v_intersection) std::cout << n << ‘ ‘; } //set_symmetric_difference计算两个集合的对称差 { std::vector<int> v1{ 1,2,3,4,5,6,7,8 }; std::vector<int> v2{ 5, 7, 9,10 }; std::sort(v1.begin(), v1.end()); std::sort(v2.begin(), v2.end()); std::vector<int> v_symDifference; std::set_symmetric_difference( v1.begin(), v1.end(), v2.begin(), v2.end(), std::back_inserter(v_symDifference)); for (int n : v_symDifference) std::cout << n << ‘ ‘;//1 2 3 4 6 8 9 10 } //set_union计算两个集合的并集 { std::vector<int> v1 = { 1, 2, 3, 4, 5 }; std::vector<int> v2 = { 3, 4, 5, 6, 7 }; std::vector<int> dest1; std::set_union(v1.begin(), v1.end(), v2.begin(), v2.end(), std::back_inserter(dest1)); for (const auto &i : dest1) { std::cout << i << ‘ ‘; } std::cout << ‘\n‘; } } //堆操作 { //is_heap检查给定的区间是否为一个堆 { std::vector<int> v{ 3, 1, 4, 1, 5, 9 }; std::cout << "initially, v: "; for (auto i : v) std::cout << i << ‘ ‘; std::cout << ‘\n‘; if (!std::is_heap(v.begin(), v.end())) { std::cout << "making heap...\n"; std::make_heap(v.begin(), v.end());//建堆。 } std::cout << "after make_heap, v: "; for (auto i : v) std::cout << i << ‘ ‘; std::cout << ‘\n‘; } //is_heap_until查找区间中为堆的最大子区间 { std::vector<int> v{ 3, 1, 4, 1, 5, 9 }; std::make_heap(v.begin(), v.end()); // 很可能扰乱堆 v.push_back(2); v.push_back(6); auto heap_end = std::is_heap_until(v.begin(), v.end()); std::cout << "all of v: "; for (auto i : v) std::cout << i << ‘ ‘; std::cout << ‘\n‘; std::cout << "only heap: "; for (auto i = v.begin(); i != heap_end; ++i) std::cout << *i << ‘ ‘; std::cout << ‘\n‘; //all of v : 9 5 4 1 1 3 2 6 //only heap : 9 5 4 1 1 3 2 } //make_heap,这个算法很有用,比如leetcode 767,我们需要每次取出最大的两个数,就需要不断地建堆和pop堆 { std::vector<int> v{ 3, 1, 4, 1, 5, 9 }; std::cout << "initially, v: "; for (auto i : v) std::cout << i << ‘ ‘; std::cout << ‘\n‘; std::make_heap(v.begin(), v.end()); std::cout << "after make_heap, v: "; for (auto i : v) std::cout << i << ‘ ‘; std::cout << ‘\n‘; std::pop_heap(v.begin(), v.end()); auto largest = v.back(); v.pop_back(); std::cout << "largest element: " << largest << ‘\n‘; std::cout << "after removing the largest element, v: "; for (auto i : v) std::cout << i << ‘ ‘; std::cout << ‘\n‘; } //push_heap { std::vector<int> v{ 3, 1, 4, 1, 5, 9 }; std::make_heap(v.begin(), v.end()); std::cout << "v: "; for (auto i : v) std::cout << i << ‘ ‘; std::cout << ‘\n‘; v.push_back(6); std::cout << "before push_heap: "; for (auto i : v) std::cout << i << ‘ ‘; std::cout << ‘\n‘; std::push_heap(v.begin(), v.end()); std::cout << "after push_heap: "; for (auto i : v) std::cout << i << ‘ ‘; std::cout << ‘\n‘; } //pop_heap { std::vector<int> v{ 3, 1, 4, 1, 5, 9 }; std::make_heap(v.begin(), v.end()); std::cout << "v: "; for (auto i : v) std::cout << i << ‘ ‘; std::cout << ‘\n‘; std::pop_heap(v.begin(), v.end()); // 移动最大元素到结尾 std::cout << "after pop_heap: "; for (auto i : v) std::cout << i << ‘ ‘; std::cout << ‘\n‘; int largest = v.back(); v.pop_back(); // 实际移出最大元素 std::cout << "largest element: " << largest << ‘\n‘; std::cout << "heap without largest: "; for (auto i : v) std::cout << i << ‘ ‘; std::cout << ‘\n‘; } //sort_heap { std::vector<int> v = { 3, 1, 4, 1, 5, 9 }; std::make_heap(v.begin(), v.end()); std::cout << "heap:\t"; for (const auto &i : v) { std::cout << i << ‘ ‘; } std::sort_heap(v.begin(), v.end()); std::cout << "\nsorted:\t"; for (const auto &i : v) { std::cout << i << ‘ ‘; } std::cout << ‘\n‘; } } //最值操作 { //max返回两个元素中的较大者 { std::cout << "larger of 1 and 9999: " << std::max(1, 9999) << ‘\n‘ << "larger of ‘a‘, and ‘b‘: " << std::max(‘a‘, ‘b‘) << ‘\n‘ << "longest of \"foo\", \"bar\", and \"hello\": " << std::max({ "foo", "bar", "hello" }, [](const std::string& s1, const std::string& s2) { return s1.size() < s2.size(); }) << ‘\n‘; } //max_element返回区间内的最大元素 { std::vector<int> v{ 3, 1, -14, 1, 5, 9 }; std::vector<int>::iterator result; result = std::max_element(v.begin(), v.end()); std::cout << "max element at: " << std::distance(v.begin(), result) << ‘\n‘; auto abs_compare=[](int a, int b) { return (std::abs(a) < std::abs(b)); }; result = std::max_element(v.begin(), v.end(), abs_compare); std::cout << "max element (absolute) at: " << std::distance(v.begin(), result); } //min //min_element //minmax { std::vector<int> v{ 3, 1, 4, 1, 5, 9, 2, 6 }; std::srand(std::time(0)); std::pair<int, int> bounds = std::minmax(std::rand() % v.size(), std::rand() % v.size()); std::cout << "v[" << bounds.first << "," << bounds.second << "]: "; for (int i = bounds.first; i < bounds.second; ++i) { std::cout << v[i] << ‘ ‘; } std::cout << ‘\n‘; } //minmax_element { std::vector<int> v = { 3, 9, 1, 4, 2, 5, 9 }; auto result = std::minmax_element(v.begin(), v.end()); std::cout << "min element at: " << (result.first - v.begin()) << ‘\n‘; std::cout << "max element at: " << (result.second - v.begin()) << ‘\n‘; } //clamp } //比较操作 { //equal { auto test=[](const std::string& s) { if (std::equal(s.begin(), s.begin() + s.size() / 2, s.rbegin())) { std::cout << "\"" << s << "\" is a palindrome\n"; } else { std::cout << "\"" << s << "\" is not a palindrome\n"; } }; test("radar"); test("hello"); } //lexicographic_compare如果按字典顺序一个区间小于另一个区间,返回true { std::vector<char> v1{ ‘a‘, ‘b‘, ‘c‘, ‘d‘ }; std::vector<char> v2{ ‘a‘, ‘b‘, ‘c‘, ‘d‘ }; std::mt19937 g{ std::random_device{}() }; while (!std::lexicographical_compare(v1.begin(), v1.end(), v2.begin(), v2.end())) { for (auto c : v1) std::cout << c << ‘ ‘; std::cout << ">= "; for (auto c : v2) std::cout << c << ‘ ‘; std::cout << ‘\n‘; std::shuffle(v1.begin(), v1.end(), g); std::shuffle(v2.begin(), v2.end(), g); } for (auto c : v1) std::cout << c << ‘ ‘; std::cout << "< "; for (auto c : v2) std::cout << c << ‘ ‘; std::cout << ‘\n‘; } //compare_3way //lexicographic_compare_3way } //排列操作 { //is_permutation { std::vector<int> v1{ 1,2,3,4,5 }; std::vector<int> v2{ 3,5,4,1,2 }; std::cout << "3,5,4,1,2 is a permutation of 1,2,3,4,5? " << std::boolalpha << std::is_permutation(v1.begin(), v1.end(), v2.begin()) << ‘\n‘; std::vector<int> v3{ 3,5,4,1,1 }; std::cout << "3,5,4,1,1 is a permutation of 1,2,3,4,5? " << std::boolalpha << std::is_permutation(v1.begin(), v1.end(), v3.begin()) << ‘\n‘; } //next_permutation 下列代码打印字符串 "aba" 的全部三种排列 { std::string s = "aba"; std::sort(s.begin(), s.end()); do { std::cout << s << ‘\n‘; } while (std::next_permutation(s.begin(), s.end())); /* 输出:aab aba baa */ } //prev_permutation { std::string s = "abc"; std::sort(s.begin(), s.end(), std::greater<char>()); do { std::cout << s << ‘ ‘; } while (std::prev_permutation(s.begin(), s.end())); std::cout << ‘\n‘; } } //数值运算 { //iota用从起始值开始连续递增的值填充区间 { std::list<int> l(10); std::iota(l.begin(), l.end(), -4); std::vector<std::list<int>::iterator> v(l.size()); std::iota(v.begin(), v.end(), l.begin()); std::shuffle(v.begin(), v.end(), std::mt19937{ std::random_device{}() }); std::cout << "Contents of the list: "; for (auto n : l) std::cout << n << ‘ ‘; std::cout << ‘\n‘; std::cout << "Contents of the list, shuffled: "; for (auto i : v) std::cout << *i << ‘ ‘; std::cout << ‘\n‘; /* Contents of the list: -4 -3 -2 -1 0 1 2 3 4 5 Contents of the list, shuffled: 0 -1 3 4 -4 1 -2 -3 2 5 */ } //accumulate //inner_product内积 { std::vector<int> a{ 0, 1, 2, 3, 4 }; std::vector<int> b{ 5, 4, 2, 3, 1 }; int r1 = std::inner_product(a.begin(), a.end(), b.begin(), 0); std::cout << "Inner product of a and b: " << r1 << ‘\n‘;//4+4+9+4=21 //value = op1(value, op2(*first1, *first2)); int r2 = std::inner_product(a.begin(), a.end(), b.begin(), 0, std::plus<>(), std::equal_to<>()); std::cout << "Number of pairwise matches between a and b: " << r2 << ‘\n‘; } //adjacent_difference计算区间内相邻元素之间的差 { std::vector<int> v{ 2, 4, 6, 8, 10, 12, 14, 16, 18, 20 }; std::adjacent_difference(v.begin(), v.end(), v.begin()); for (auto n : v) { std::cout << n << ‘ ‘; } std::cout << ‘\n‘; // 斐波那契 // 注意,列表中下一项是当前迭代的结果 v = std::vector<int>(10); v[0] = 1; std::adjacent_difference(v.begin(), v.end() - 1, v.begin() + 1, std::plus<int>()); for (auto n : v) { std::cout << n << ‘ ‘; } std::cout << ‘\n‘; } //partial_sum { std::vector<int> v = { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 }; // 或 std::vector<int>v(10, 2); std::cout << "The first 10 even numbers are: "; std::partial_sum(v.begin(), v.end(), std::ostream_iterator<int>(std::cout, " ")); std::cout << ‘\n‘; std::partial_sum(v.begin(), v.end(), v.begin(), std::multiplies<int>()); std::cout << "The first 10 powers of 2 are: "; for (auto n : v) { std::cout << n << " "; } std::cout << ‘\n‘; } //reduce类似于accumulate { std::vector<double> v(10‘000‘007, 0.5); { auto t1 = std::chrono::high_resolution_clock::now(); double result = std::accumulate(v.begin(), v.end(), 0.0); auto t2 = std::chrono::high_resolution_clock::now(); std::chrono::duration<double, std::milli> ms = t2 - t1; std::cout << std::fixed << "std::accumulate result " << result << " took " << ms.count() << " ms\n"; } //VS尚不支持 //{ // auto t1 = std::chrono::high_resolution_clock::now(); // double result = std::reduce(std::execution::par, v.begin(), v.end()); // auto t2 = std::chrono::high_resolution_clock::now(); // std::chrono::duration<double, std::milli> ms = t2 - t1; // std::cout << "std::reduce result " // << result << " took " << ms.count() << " ms\n"; //} } //exclusive_scan尚不支持 { } //inclusive_scan尚不支持 } //未初始化内存上的操作 { //uninitialized_copy将范围内的对象复制到未初始化的内存区域 //本质是调用placementNew //::new (static_cast<void*>(std::addressof(*current))) Value(*first); { std::vector<std::string> v = { "This", "is", "an", "example" }; std::string* p; std::size_t sz; std::tie(p, sz) = std::get_temporary_buffer<std::string>(v.size()); sz = std::min(sz, v.size()); std::uninitialized_copy(v.begin(), v.begin() + sz, p); for (std::string* i = p; i != p + sz; ++i) { std::cout << *i << ‘ ‘; i->~basic_string<char>(); } std::return_temporary_buffer(p); } //uninitialized_copy_n { std::vector<std::string> v = { "This", "is", "an", "example" }; std::string* p; std::size_t sz; std::tie(p, sz) = std::get_temporary_buffer<std::string>(v.size()); sz = std::min(sz, v.size()); std::uninitialized_copy_n(v.begin(), sz, p); for (std::string* i = p; i != p + sz; ++i) { std::cout << *i << ‘ ‘; i->~basic_string<char>(); } std::return_temporary_buffer(p); } //uninitialized_fill复制一个对象到以范围定义的未初始化内存区域 { std::string* p; std::size_t sz; std::tie(p, sz) = std::get_temporary_buffer<std::string>(4); std::uninitialized_fill(p, p + sz, "Example"); for (std::string* i = p; i != p + sz; ++i) { std::cout << *i << ‘\n‘; i->~basic_string<char>(); } std::return_temporary_buffer(p); } //uninitialized_fill_n //以下均为C++17支持 //uninitialized_move { /*可能的实现 template<class InputIt, class ForwardIt> ForwardIt uninitialized_move(InputIt first, InputIt last, ForwardIt d_first) { typedef typename std::iterator_traits<ForwardIt>::value_type Value; ForwardIt current = d_first; try { for (; first != last; ++first, (void) ++current) { ::new (static_cast<void*>(std::addressof(*current))) Value(std::move(*first)); } return current; } catch (...) { for (; d_first != current; ++d_first) { d_first->~Value(); } throw; } } //关键代码是::new (static_cast<void*>(std::addressof(*current))) Value(std::move(*first)); //初始化对象时以右值构造 */ } //uninitialized_move_n //uninitialized_default_construct //uninitialized_default_construct_n //uninitialized_value_construct //uninitialized_vaule_construct_n //destroy_at //destroy //destroy_n } //C库 { //qsort //无关乎名称, C++ 、 C 及 POSIX 都不要求此函数用快速排序实现或作出任何复杂度和稳定性保证。 { int a[] = { -2, 99, 0, -743, 2, INT_MIN, 4 }; constexpr std::size_t size = sizeof a / sizeof *a; std::qsort(a, size, sizeof *a, [](const void* a, const void* b) { int arg1 = *static_cast<const int*>(a); int arg2 = *static_cast<const int*>(b); if (arg1 < arg2) return -1; if (arg1 > arg2) return 1; return 0; // 返回 (arg1 > arg2) - (arg1 < arg2); // 可行的缩写 // 返回 arg1 - arg2; // 错误的缩写(若有 INT_MIN 则失败) }); for (int ai : a) std::cout << ai << ‘ ‘; } //bsearch { const int ARR_SIZE = 8; int arr[ARR_SIZE] = { 1, 2, 3, 4, 5, 6, 7, 8 }; int key1 = 4; auto compare=[](const void *ap, const void *bp) { auto a = static_cast<const int *>(ap); auto b = static_cast<const int *>(bp); if (*a < *b) return -1; else if (*a > *b) return 1; else return 0; }; int *p1 = (int *)std::bsearch(&key1, arr, ARR_SIZE, sizeof(arr[0]), compare); if (p1) std::cout << "value " << key1 << " found at position " << (p1 - arr) << ‘\n‘; else std::cout << "value " << key1 << " not found\n"; int key2 = 9; int *p2 = (int *)std::bsearch(&key2, arr, ARR_SIZE, sizeof(arr[0]), compare); if (p2) std::cout << "value " << key2 << " found at position " << (p2 - arr) << ‘\n‘; else std::cout << "value " << key2 << " not found\n"; } } { vector<int> vec_int{ 1,2,2,3,3,3,4,4,4,4,5,6,26,17,8,19,10 }; vector<string> vec_string{ "i","love","you" }; } return 0; }
原文地址:https://www.cnblogs.com/lsaejn/p/9733729.html
时间: 2024-11-08 20:30:52