1.简介
STL标准中,没有区分基本算法和复杂算法,然而SGI STL却把常用的算法定义在<stl_algorithms.h>中。本文介绍部分<stl_algorithms.h>算法的实现,给出实现代码和测试代码。
本文介绍的算法包括:
1. mismatch:比较两个序列,指出两者之间第一个不匹配的点,返回一对迭代器,分别指向两序列中不匹配的点;
2. equal:如果两个序列在 [first, last ] 区间内相等,equal() 返回true,忽略第二个序列的元素多出来的部分;
3. fill:将 [ first,last ) 内的所有元素值改填为 value;
4. fill_n:将 [ first,last ) 内的前 n 个元素值改填为 value ,返回迭代器,指向被填入的最后一个元素的下一位置;
5. iter_sawp:将两个迭代器(ForwardIterator)所指的对象对调;
6. lexicographical_compare:以“字典排列方式”对两个序列 [first1, last1 ) 和 [ first2, last2 )进行比较;
7. max、min:比较大小;
2.设计与实现
我用VS2013写的程序(github),数值算法的实现版本的位于cghSTL/version/cghSTL-0.5.2.rar
本文介绍的算法实现需要以下文件:
1. cghVector.h,自己实现的vector,位于cghSTL/sequence
containers/cghVector/,想了解vector实现细节的同学请移步:STL简单vector的实现
2. cghUtil.h:算法的输出会用到pair结构体,我把pair自己实现了一遍,位于cghSTL/cghUtil/
3. cghStl_algobase.h,本文的主角:算法的源码,位于cghSTL/algorithms/
4. test_algorithms_algobase.cpp,测试文件,位于cghSTL/test/
为了增强代码的可读性,我用region把各个算法隔开,如下图所示
copy算法的实现略微复杂,单独开博客介绍,其余的算法都很简单,直接上代码吧,注释已经说明了一切~
cghStl_algobase.h
/******************************************************************* * Copyright(c) 2016 Chen Gonghao * All rights reserved. * * [email protected] * * 文件内容:equal、fill、fill_n、iter_sawp、max、min、 lexicographical_compare、mismatch、copy 算法的实现 ******************************************************************/ #ifndef _CGH_STL_ALGOBASE_ #define _CGH_STL_ALGOBASE_ #include "cghUtil.h" #include "cghSTL_type_traits.h" #include "cghSTL_iterator.h" namespace CGH{ #pragma region equal /* 如果两个序列在 [ first, last ] 区间内相等,equal() 返回true,忽略第二个序列的元素多出来的部分 */ template<class InputIterator1, class InputIterator2> inline bool equal(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2) { for (; first1 != last1; ++first1, ++first2) { if (*first1 != *first2) { return false ; // 如果同一位置上的两个元素值不相等,返回false } } // 当第一个序列走完时(第二个序列一定要比第一个长,且不考虑第二个序列多出来的部分) // 两个序列相同位置的元素全部相等,返回true return true ; } /* 如果两个序列在 [ first, last ] 区间内相等,equal() 返回true,忽略第二个序列的元素多出来的部分 binaryPredicate:用户自定义的比较函数 */ template<class InputIterator1, class InputIterator2, class binaryPredicate> inline bool equal(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, binaryPredicate binary_pred) { for (; first1 != last1; ++first1, ++first2) { if (!(binaryPredicate(*first1, *first2))) { return false ; // 如果同一位置上的两个元素值不相等(采用用户自定义的大小比较函数:binaryPredicate),返回false } } // 当第一个序列走完时(第二个序列一定要比第一个长,且不考虑第二个序列多出来的部分) // 两个序列相同位置的元素全部相等,返回true return true ; } #pragma endregion #pragma region fill /* 将 [ first, last ) 内的所有元素值改填为 value */ template<class ForwardIterator, class T> void fill(ForwardIterator first, ForwardIterator last, const T& value) { for (; first != last; ++first) { *first = value ; } } #pragma endregion #pragma region fill_n /* 将 [ first, last ) 内的前 n 个元素值改填为 value ,返回迭代器,指向被填入的最后一个元素的下一位置 */ template<class OutputIterator, class size, class T> OutputIterator fill_n(OutputIterator first, size n, const T& value) { for (; n > 0; --n, ++first) { *first = value; } return first; } #pragma endregion #pragma region iter_sawp /* 将两个迭代器(ForwardIterator)所指的对象对调 */ template<class ForwardIterator1, class ForwardIterator2> void iter_swap(ForwardIterator1 first, ForwardIterator2 last) { // iterator_traits:特性萃取机,获得迭代器指向的值类型 std::iterator_traits<ForwardIterator1>::value_type tmp = *first; *first = *last; *last = tmp; } #pragma endregion #pragma region max min /* 比较大小 */ template<class T> inline const T& max(const T& a, const T& b) { return a > b ? a : b ; } /* compare:用户自定义的大小比较函数 */ template<class T, class compare> inline const T& max(const T& a, const T& b, compare comp) { return comp(a, b) ? a : b ; } /* 比较大小 */ template<class T> inline const T& min(const T& a, const T& b) { return a < b ? a : b ; } /* compare:用户自定义的大小比较函数 */ template<class T, class compare> inline const T& min(const T& a, const T& b, compare comp) { return comp(a, b) ? b : a ; } #pragma endregion #pragma region lexicographical_compare /* 以“字典排列方式”对两个序列 [ first1, last1 ) 和 [ first2, last2 )进行比较,第一个序列以字典排序不小于第二个序列 比较操作针对两个序列中对应位置上的元素进行,直到一下情况出现: 1.两序列同一位置上的元素不相等; 2.同时到达 last1 和 last2(两序列相等); 3.到达 last1 或者 last2(两序列不相等); */ /* 两序列第一次出现同一位置上元素不相等时,lexicographical_compare() 函数的返回值有一下可能: 1.如果第一个序列的元素比较小,返回 true ,否则返回 false; 2.如果到达 last1 而尚未到达 last2,返回 true; 3.如果到达 last2 而尚未到达 last1,返回 false; 4.如果同时到达 last1 和 last2(注意,序列的区间是前闭后开,同时到达 last 说明所有元素都匹配),返回false; */ template<class InputIterator1, class InputIterator2> bool lexicographical_compare(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2) { // 以下任何一个序列到达尾端,就结束。,否则两序列一一比对相应元素 for (; first1 != last1 && first2 != last2; ++first1, ++first2) { if (*first1 < *first2) { return true ; // 第一序列值小于第二序列相应值,返回 true } if (*first2 < *first1) { return false ; // 第一序列值大于第二序列相应值,返回 false } // 如果两序列同一位置元素相等,进入迭代器前进,下一轮比较 } // 如果第一个序列到达尾端,但是第二个序列仍有剩余,那么第一个序列小于第二个序列 return first1 == last1 && first2 != last2 ; } /* compare:用户指定的大小比较方法 */ template<class InputIterator1, class InputIterator2, class compare> bool lexicographical_compare(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, compare comp) { for (; first1 != last1 && first2 != last2; ++first1, ++first2) { if ( comp( *first1, *first2 ) ) { return true ; } if ( comp(*first2, *first1) ) { return false ; } } return first1 == last1 && first2 != last2 ; } /* 为了增强效率,设计了特化版,使用原生指针 const unsigned char* */ bool lexicographical_compare(const unsigned char* first1, const unsigned char* last1, const unsigned char* first2, const unsigned char* last2) { const size_t len1 = last1 - first1 ; // 第一个序列的长度 const size_t len2 = last2 - first2 ; // 第二个序列的长度 const int result = memcmp(first1, first2, CGH::min(len1, len2)); // 使用memcmp比较长度相同的部分 return result != 0 ? result < 0 : len1 < len2 ; // 如果不相上下,则长度较长者视为比较大 } #pragma endregion #pragma region mismatch /* 比较两个序列,指出两者之间第一个不匹配的点,返回一对迭代器,分别指向两序列中不匹配的点 如果两序列对应元素都匹配,返回的便是两序列各自的 last 迭代器 如果第二个序列比第一个序列长,忽略多出来的部分 默认情况下是 equality 操作符比较元素 */ template<class InputIterator1, class InputIterator2> cghPair<InputIterator1, InputIterator2> mismatch(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2) { while (first1 != last1 && *first1 == *first2) { ++first1; ++first2; } return cghPair<InputIterator1, InputIterator2>(first1, first2) ; } /* BinaryPredicator:用户自定义比较操作 */ template<class InputIterator1, class InputIterator2, class BinaryPredicator> cghPair<InputIterator1, InputIterator2> mismatch(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, BinaryPredicator binary_pre) { while (first1 != last1 && binary_pre(*first1, *first2)) { ++first1; ++first2; } return cghPair<InputIterator1, InputIterator2>(first1, first2) ; } #pragma endregion } #endif
3.测试
测试环节的主要内容已在注释中说明
test_algorithms_algobase.cpp
/******************************************************************* * Copyright(c) 2016 Chen Gonghao * All rights reserved. * * [email protected] * * 文件内容:cghStl_algobase.h 中的数值算法的测试 ******************************************************************/ #include "stdafx.h" #include "cghVector.h" #include "cghStl_algobase.h" #include <string> #include <iterator> #include "cghUtil.h" int _tmain(int argc, _TCHAR* argv[]) { using namespace::CGH; std::cout << "创建vector1,依次 puah_back 1、2、3、4、5" << std::endl << std::endl; cghVector<int> vector1; vector1.push_back(1); vector1.push_back(2); vector1.push_back(3); vector1.push_back(4); vector1.push_back(5); std::cout << "创建vector2,依次 puah_back 1、2、8、9、0" << std::endl << std::endl; cghVector<int> vector2; vector2.push_back(1); vector2.push_back(2); vector2.push_back(8); vector2.push_back(9); vector2.push_back(0); std::ostream_iterator<int> oite(std::cout, " "); std::cout << "***********************测试 mismatch 算法**********************" << std::endl << std::endl; std::cout << "返回一对迭代器,指出 vector1 和 vector2 的第一个不相等元素:" ; std::cout << *(CGH::mismatch(vector1.begin(), vector1.end(), vector2.begin()).first) << ", "; std::cout << *(CGH::mismatch(vector1.begin(), vector1.end(), vector2.begin()).second); std::cout << std::endl << std::endl << std::endl; std::cout << "************************测试 equal 算法************************" << std::endl << std::endl; std::cout << "判断 vector1 和 vector2 是否相等:"; std::string isEqual = equal(vector1.begin(), vector1.end(), vector2.begin(), vector2.end()) == 0 ? "不相等" : "相等" ; std::cout << isEqual << std::endl << std::endl; std::cout << "用户指定 less<int>() 函数,判断 vector1 和 vector2 的大小:"; std::string isLess = equal(vector1.begin(), vector1.end(), vector2.begin(), std::less<int>()) == 0 ? "vector1 小于 vector2" : "vector1 大于 vector2" ; std::cout << isLess << std::endl << std::endl << std::endl; std::cout << "*************************测试 fill 算法************************" << std::endl << std::endl; std::cout << "将 vector1 的所有元素改填为 9:" << std::endl << std::endl; CGH::fill(vector1.begin(), vector1.end(), 9); for (int i = 0; i < vector1.size(); ++i) { std::cout << "vector1[" << i << "] = " << vector1[i] << std::endl; } std::cout << std::endl << std::endl; std::cout << "************************测试 fill_n 算法***********************" << std::endl << std::endl; std::cout << "将 vector1 的前3个元素改填为 0:" << std::endl << std::endl; CGH::fill_n(vector1.begin(), 3, 0); for (int i = 0; i < vector1.size(); ++i) { std::cout << "vector1[" << i << "] = " << vector1[i] << std::endl; } std::cout << std::endl << std::endl; std::cout << "***********************测试 iter_sawp 算法**********************" << std::endl << std::endl; std::cout << "交换 vector1[0] 和 vector2[0],交换前,vector1[0] = " << vector1[0] << ",vector2[0] = " << vector2[0] << std::endl; CGH::iter_swap(vector1.begin(), vector2.begin()); std::cout << std::endl; std::cout << "交换后,vector1[0] = " << vector1[0] << ",vector2[0] = " << vector2[0] << std::endl; std::cout << std::endl << std::endl; std::cout << "****************测试 lexicographical_compare 算法***************" << std::endl << std::endl; std::string str1[] = {"test", "Cgh"}; std::string str2[] = {"test", "cgh"}; std::cout << "现有 str1[] = {\"test\", \"Cgh\"} 和 str2[] = {\"test\", \"cgh\"}" << std::endl << std::endl; std::cout << "比较 str1[] 和 str2[] 的大小:" ; std::string str1Str2 = CGH::lexicographical_compare(str1, str1 + 1, str2, str2 + 1) == true ? "str1[] 大于 str2[]" : "str1[] 小于 str2[]"; std::cout << str1Str2 << std::endl; std::cout << std::endl << std::endl; std::cout << std::endl; system("pause"); return 0; }
结果如下图所示: