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.
*
* chengonghao@yeah.net
*
* 文件内容: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.
*
* chengonghao@yeah.net
*
* 文件内容: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;
}
结果如下图所示: