STL算法详细解剖——单纯数据处理函数

news2024/12/23 3:54:49

STL算法详细解剖——单纯数据处理函数

  • 前言
    • 1.replace 替代函数值
    • 2.replace_copy 替代函数值
    • 3.replace_if 替代函数值
    • 4.replace_copy_if 替代函数值
    • 5.reverse 颠倒排序
    • 6.reverse_copy 颠倒排序
    • 7.rotate 将元素按某个中间值进行互换
    • 7.1.rotate 将元素按某个中间值进行互换
    • 8.roate_copy 将元素按某个中间值进行互换
    • 9.search 判断是否包含子串
    • 10.search_n 查找n个满足条件的元素所组成的子串
    • 11.swap_ranges 等长区间的元素进行互换
    • 12.transform 提供的仿函数用于区间每个元素
    • 13.adjacent_find 查找相邻的重复元素
    • 14.unique 移除相邻的重复元素(并不删除空间)
    • 15.count 查找某个元素的个数
    • 16.count_if 查找某个元素的个数
    • 17.find 查找某个元素返回一个迭代器
    • 18.find_if 查找某个元素返回一个迭代器
    • 19.find_end 查找完全匹配的子串最后出现的位置
    • 20.find_first_of 查找目标区的元素在源区第一次出现的位置
    • 21.for_each 遍历数据
    • 22. generate 将仿函数运行的结果填入源区间元素中
    • 23. generate_n 运算结果填写到从迭代器开始的n个元素身上
    • 24. includes (应用有序区间),验证目标集合是否为源集合的子集
    • 25. max_element 返回一个指向最大元素的迭代器
    • 26. merge(应用有序区间)将两个排序的集合存放在另一个空间中
    • 27. min_element 返回一个指向最小值的迭代器
    • 28. partition 区间内的集合,判断为true的放前面,判断为false放后面
    • 29. remove 删除指定元素(并不删除空间)
    • 30. remove_copy 删除指定元素,结果存放在另外一个空间
    • 31. remove_if remove_copy_if 删除区间内,被仿函数评估为true的元素
  • 总结

前言

阅读STL源码剖析有感,简单模拟处理函数的实现,同时也写了部分函数的测试代码,读者这直接复制粘贴使用(若有问题,请多多指出)。这份总结的目的是了解函数背后的运行,体会模板函数与仿函数结合的奥妙。在日常的开发中,可用相关的函数,来满足日常开发的需求。增加代码的可读性,减小代码的体积。(为了防止函数命名冲突,函数前面追加了自定义 USD_ 来重新命名函数)

1.replace 替代函数值

template<class T_iterator,class T>
void replace(T_iterator first, T_iterator last, const T& old_value, const T& new_value)
{
        for (;first != last;++first )
        {
                if (*first == old_value)
                {
                        *first = new_value;
                }
        }
}

int main()
{
        int a[] = {1,2,3,3,3,5,6};
        std::vector<int> vecTest(a, a+7);
        replace(vecTest.begin(), vecTest.end(),3,4);
        return 0;
}

通过遍历数据,当查找到对应数据时,修改数据值

2.replace_copy 替代函数值

template<class IntputIterator, class OutputIterator, class T>
OutputIterator replace_copy(IntputIterator first, IntputIterator last, OutputIterator result, const T& old_value, const T& new_value)
{
        for (; first != last; ++first,++result)
        {
                *result = *first == old_value ? new_value : *first;
        }
        return result;
}


int main()
{
        int a[] = {1,2,3,3,3,5,6};
        std::vector<int> vecTest(a, a+7);
        std::vector<int> vecReslutTest;
        vecReslutTest.resize(7);
        replace_copy(vecTest.begin(), vecTest.end(), vecReslutTest.begin(),3,4);
        return 0;
}

通过遍历数据,当查找到对应数据时,修改数据值。将修改的数据存储到另外一个空间中

3.replace_if 替代函数值

template<class ForwardIterator, class Predicate, class T>
void replace_if(ForwardIterator first, ForwardIterator last, Predicate pred, const T& new_value)
{
        for (; first != last; ++first)
        {
                if (pred(*first))
                {
                        *first = new_value;
                }
        }
        
}

class Predicate
{
public:
        Predicate(int x)
        {
                m_x = x;
        }

        bool operator()(int value)
        {
                if (value == m_x)
                {
                        return true;
                }
                return false;
        }
private:
        int m_x;
};

int main()
{
        int a[] = {1,2,3,3,3,5,6};
        std::vector<int> vecTest(a, a+7);
        std::vector<int> vecReslutTest;
        vecReslutTest.resize(7);
        replace_copy(vecTest.begin(), vecTest.end(), vecReslutTest.begin(),3,4);
        replace_if(vecTest.begin(), vecTest.end(), Predicate(3),4);
        return 0;
}

上述操作和之前的逻辑相似,此处的设计逻辑可用于以后对不同数据类型的逻辑处理。不同类型的数据修改成不同的仿函数使用

4.replace_copy_if 替代函数值

class Predicate
{
public:
        Predicate(int x)
        {
                m_x = x;
        }

        bool operator()(int value)
        {
                if (value == m_x)
                {
                        return true;
                }
                return false;
        }
private:
        int m_x;
};

template<class IntputIterator, class OutputIterator, class Predicate, class T>
OutputIterator replace_copy_if(IntputIterator first, IntputIterator last, OutputIterator result, Predicate pred, const T& new_value)
{
        for (; first != last; ++first, result++)
        {
                *result = pred(*first) ? new_value : *first;
        }
        return result;
}

int main()
{
        int a[] = {1,2,3,3,3,5,6};
        std::vector<int> vecTest(a, a+7);
        std::vector<int> vecReslutTest;
        vecReslutTest.resize(7);
        replace_copy_if(vecTest.begin(), vecTest.end(), vecReslutTest.begin(), Predicate(3), 4);
        return 0;
}

此算法和上述相似,只是将修改后的结果存放到另外一个空间

5.reverse 颠倒排序

template<class ForwardIterator1, class ForwardIterator2>
void _iter_swap(ForwardIterator1 a, ForwardIterator2 b)
{
        typename std::iterator_traits<ForwardIterator1>::value_type tmp = *a;
        *a = *b;
        *b = tmp;
}


template<class ForwardIterator1, class ForwardIterator2>
void usd_iter_swap(ForwardIterator1 a, ForwardIterator2 b)
{
        
        _iter_swap(a,b);
}

template<class ForwardIterator>
void _reverse(ForwardIterator first, ForwardIterator last)
{
        while (true)
        {
                if (first == last || first == --last)
                {
                        return;
                }
                else
                {
                        usd_iter_swap(first++, last);
                }
        }
}

int main()
{
        int a[] = {1,2,3,3,3,5,6};
        std::vector<int> vecTest(a, a+7);
        std::vector<int> vecReslutTest;
        vecReslutTest.resize(7);
        _reverse(vecTest.begin(), vecTest.end());
        return 0;
}

遍历数据,首尾数据互换。颠倒结束后,返回排序

6.reverse_copy 颠倒排序

template<class IntputIterator, class OutputIterator>
void reverse_copy(IntputIterator first, IntputIterator last, OutputIterator result)
{
        while (first != last)
        {
                --last;
                *result = *last;
                result++;
        }
}

int main()
{
        int a[] = {1,2,3,3,3,5,6};
        std::vector<int> vecTest(a, a+7);
        std::vector<int> vecReslutTest;
        //replace(vecTest.begin(), vecTest.end(), 3, 4);
        vecReslutTest.resize(7);
        //replace_copy(vecTest.begin(), vecTest.end(), vecReslutTest.begin(),3,4);
        //replace_if(vecTest.begin(), vecTest.end(), Predicate(3),4);
        //replace_copy_if(vecTest.begin(), vecTest.end(), vecReslutTest.begin(), Predicate(3), 4);
        //_reverse(vecTest.begin(), vecTest.end());
        reverse_copy(vecTest.begin(), vecTest.end(), vecReslutTest.begin());
        return 0;
}

逆序遍历数据,将遍历的数据存储到另外一个起来,相比上一个算法步骤减少很多

7.rotate 将元素按某个中间值进行互换

在这里插入图片描述

template<class ForwardIterator1, class ForwardIterator2>
void _iter_swap(ForwardIterator1 a, ForwardIterator2 b)
{
        typename std::iterator_traits<ForwardIterator1>::value_type tmp = *a;
        *a = *b;
        *b = tmp;
}

template<class ForwardIterator>
void roate(ForwardIterator first, ForwardIterator middle, ForwardIterator last)
{
        for (ForwardIterator i = middle;;)
        {
                _iter_swap(first,i);
                first++;
                i++;
                if (first == middle)
                {
                        if (i == last)
                        {
                                return;
                        }
                        else
                        {
                                middle = i;
                        }
                }
                else if(i == last)
                {
                        i = middle;
                }
        }
}

int main()
{
        std::ostream_iterator<int> outite(std::cout," ");
        int ia[6] = { 1,2,3,4,5,6 };
        std::vector<int> iv(ia, ia+6);
        roate(iv.begin(),iv.begin() +3, iv.end());
        return 0;
}

将数据进行通过中间值进行旋转,采用交换的算法。同时考虑:1.数据等长 2.数据前长后短 3.数据前短后长。

7.1.rotate 将元素按某个中间值进行互换

[图片]

template<class ForwardIterator>
void _roate(ForwardIterator first, ForwardIterator middle, ForwardIterator last)
{
        std::reverse(first, middle);
        std::reverse(middle, last);
        std::reverse(first, last);
}

int main()
{
        std::ostream_iterator<int> outite(std::cout," ");
        int ia[6] = { 1,2,3,4,5,6 };
        std::vector<int> iv(ia, ia+6);
        _roate(iv.begin(),iv.begin()+4, iv.end());
        return 0;
}

根据迭代器的作用,此方法更简单,通过对两段数据的逆转,之后在对整个数据进行逆转,就可以达到效果

8.roate_copy 将元素按某个中间值进行互换

template<class ForwardIterator,class OutputIterator>
void roate_copy(ForwardIterator first, ForwardIterator middle, ForwardIterator last, OutputIterator result)
{
        copy(first, middle,copy(middle,last, result));
}


int main()
{
        int ia[6] = { 1,2,3,4,5,6 };
        std::vector<int> iv(ia, ia+6);
        std::vector<int> vecResult;
        _roate(iv.begin(),iv.begin()+4, iv.end());
        vecResult.resize(6);
        roate_copy(iv.begin(), iv.begin() + 4, iv.end(), vecResult.begin());
        return 0;
}

通过拷贝操作,将后一段信息拷贝到另外一个空间的前端,在拷贝前一段信息

9.search 判断是否包含子串

template<class ForwardIterator>
typename std::iterator_traits<ForwardIterator>::difference_type USD_distance(ForwardIterator first,ForwardIterator last)
{
        typename std::iterator_traits<ForwardIterator>::difference_type n = 0;
        while (first != last)
        {
                ++first;
                ++n;
        }
        return n;
}

template<class ForwardIterator1, class ForwardIterator2>
ForwardIterator1 USD_search(ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2)
{
        typename std::iterator_traits<ForwardIterator1>::difference_type d1 = 0;
        d1 = USD_distance(first1, last1);
        typename std::iterator_traits<ForwardIterator2>::difference_type d2 = 0;
        d2 = USD_distance(first2, last2);

        if (d1 < d2)
        {
                return last1;
        }
        ForwardIterator1 current1 = first1;
        ForwardIterator2 current2 = first2;
        while (current2 != last2)
        {
                if (*current2 == *current1)
                {
                        ++current1;
                        ++current2;
                }
                else
                {
                        if (d1 == d2)
                        {
                                return last1;
                        }
                        current1 = ++first1;
                        current2 = first2;
                        d1--;
                }
        }
        return first1;
}

int main()
{
        int ia[6] = { 1,2,3,4,5,6 };
        std::vector<int> iv(ia, ia+6);

        int iav[3] = {4,5,6 };
        std::vector<int> ivec(iav, iav + 3);
        std::vector<int>::iterator item = USD_search(iv.begin(), iv.end(), ivec.begin(), ivec.end());
        return 0;
}

遍历子串,判断子串每个元素是否等于目标串中的值 当有不相等的值时,目标串开始位置前进一格,重新开始遍历子串,以此往复。

10.search_n 查找n个满足条件的元素所组成的子串

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

template<class T>
class USD_greater
{
public:
        USD_greater()
        {

        }

        bool operator()(T leftValue, T rightValue)
        {
                if (leftValue > rightValue)
                {
                        return true;
                }
                return false;
        }
};

template<class ForwardIterator, class Integer,class T,class pred>
ForwardIterator USD_search_n(ForwardIterator first, ForwardIterator last, Integer count,const T& value, pred binary_pred)
{
        if (count < 0)
        {
                return first;
        }
        else
        {
                while (first != last)
                {
                        if (binary_pred(*first,value))
                        {
                                break;
                        }
                        first++;
                }
                while (first != last)
                {
                        Integer n = count - 1;
                        ForwardIterator i = first;
                        ++i;
                        while (i != last && n > 0 && binary_pred(*i, value))
                        {
                                --n;
                                ++i;
                        }
                        if (n == 0)
                        {
                                return first;
                        }
                        else
                        {
                                while (i != last)
                                {
                                        if (binary_pred(*i, value))
                                        {
                                                break;
                                        }
                                        i++;
                                }
                        }
                        first = i;
                }
        }
}

int main()
{
        int ia[7] = { 1,2,3,4,3,5,6 };
        std::vector<int> iv(ia, ia+7);
        std::vector<int>::iterator item = USD_search_n(iv.begin(), iv.end(),2,3, USD_greater<int>());
        return 0;
}

通过遍历数据,查找到符合条件的第一个元素。在此位置进行遍历,查找n个元素是否相等。若不满足条件,查找下一个符合条件的第一个元素

11.swap_ranges 等长区间的元素进行互换

template<class ForwardIterator1, class ForwardIterator2>
void _iter_swap(ForwardIterator1 a, ForwardIterator2 b)
{
        typename std::iterator_traits<ForwardIterator1>::value_type tmp = *a;
        *a = *b;
        *b = tmp;
}

template<class ForwardIterator1, class ForwardIterator2>
ForwardIterator2 USD_swap_ranges(ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2)
{
        for (; first1 != last1; ++first1, ++first2)
        {
                iter_swap(first1, first2);
        }
        return first2;
}

int main()
{
        int ia[7] = { 1,1,1 };
        std::vector<int> iv(ia, ia+3);

        int iav[3] = {4,5,6 };
        std::vector<int> ivec(iav, iav + 3);
        std::vector<int>::iterator item = USD_swap_ranges(iv.begin(), iv.end(), ivec.begin());
        return 0;
}

遍历数据,将两个串的数据,通过交换函数,将两个值进行对换。

12.transform 提供的仿函数用于区间每个元素

template<class T>
class multiply
{
public:
        multiply(int value)
        {
                m_value = value;
        }
        T operator()(int value)
        {
                return value = m_value * value;
        }
private:
        T m_value;
};

template<class InputIterator, class OutputIterator,class UnaryOperation>
OutputIterator USD_transform(InputIterator first, InputIterator last, OutputIterator result, UnaryOperation op)
{
        for (; first != last; ++first, ++result)
        {
                *result = op(*first);
        }
        return first;
}

//第二个版本,处理方式,前后两个数据进行处理,将所得到的结果存储起来。(与上一个版本相比,只是仿函数多了一个参数)
template<class InputIterator, class OutputIterator, class BinaryOperation>
OutputIterator USD_transform(InputIterator first, InputIterator last, InputIterator first2, OutputIterator result, BinaryOperation Binary_op)
{
        for (; first != last; ++first, ++first2, ++result)
        {
                *result = Binary_op(*first, *first2);
        }
        return first;
}
int main()
{
        int ia[3] = { 1,2,3 };
        std::vector<int> iv(ia, ia+3);

        std::vector<int> ivec;
        ivec.resize(3);
        USD_transform(iv.begin(), iv.end(), ivec.begin(), multiply<int>(2));
        return 0;
}

遍历数据,将数据通过仿函数进行处理。可用于处理集合中的所有数据。

13.adjacent_find 查找相邻的重复元素

template<class ForwardIterator>
ForwardIterator USD_adjacent_find(ForwardIterator first, ForwardIterator last)
{
        if (first == last)
        {
                return last;
        }
        ForwardIterator next = first;
        while (++next != last)
        {
                if (*first == *next)
                {
                        return first;
                }
                first = next;
        }
        return last;
}

int main()
{
        int ia[5] = { 1,2,2,2,3 };
        std::vector<int> iv(ia, ia+5);
        std::vector<int>::iterator item = USD_adjacent_find(iv.begin(), iv.end());
        return 0;
}

元素重复,即判断两个相邻的元素是否相等。判断第一个元素和第二个元素是否相等,不相等,将第二个元素,作为首元素,将下一个元素作为第二个元素两者相比,以此类推。

14.unique 移除相邻的重复元素(并不删除空间)

template<class ForwardIterator>
ForwardIterator USD_adjacent_find(ForwardIterator first, ForwardIterator last)
{
        if (first == last)
        {
                return last;
        }
        ForwardIterator next = first;
        while (++next != last)
        {
                if (*first == *next)
                {
                        return first;
                }
                first = next;
        }
        return last;
}

template<class InputIterator,class OutputIterator>
OutputIterator USD_unique_copy(InputIterator first, InputIterator last, OutputIterator result)
{
        if (first == last)
        {
                return result;
        }
        typename std::iterator_traits<InputIterator>::value_type value = *first;
        *result = value;
        while (++first != last)
        {
                if (value != *first)
                {
                        value = *first;
                        *++result = value;
                }
        }
        return result;
}

template<class ForwardIterator>
ForwardIterator USD_unique(ForwardIterator first, ForwardIterator last)
{
        first = USD_adjacent_find(first,last);
        return USD_unique_copy(first,last, first);
}

int main()
{
        int ia[5] = { 1,2,2,2,3 };
        std::vector<int> iv(ia, ia+5);
        std::vector<int>::iterator item = USD_adjacent_find(iv.begin(), iv.end());
        USD_unique(iv.begin(), iv.end());

        std::vector<int> ivec;
        ivec.resize(5);
        //USD_unique_copy(iv.begin(), iv.end(), ivec.begin());
        return 0;
}

此算法的设计主要依靠unique_copy(),该算法的逻辑:记录第一个值,判断与下一个值是否相等。如果相等跳过,进行下一个数据的比较。如果数据不相等,记录数据在结果中,同时更新比较的值为当前数据的值。(注意:此函数,也是通过改写内容来达到删除数据的效果)

15.count 查找某个元素的个数

template <class InputIterator,class T>
typename std::iterator_traits<InputIterator>::difference_type USD_count(InputIterator first, InputIterator last, const T& value)
{
        typename std::iterator_traits<InputIterator>::difference_type n = 0;
        for (; first != last; first++)
        {
                if (value == *first)
                {
                        n++;
                }
        }
        return n;
}

int main()
{
        int ia[5] = { 1,2,2,2,3 };
        std::vector<int> iv(ia, ia+5);
        int n = USD_count(iv.begin(), iv.end(), 2);
        return 0;
}

此算法通过遍历数据,统计满足条件的数据个数

16.count_if 查找某个元素的个数

template<class T>
class compere
{
public:
        compere()
        {

        }

        bool operator()(T Value)
        {
                if (Value > 2)
                {
                        return true;
                }
                return false;
        }

};

template <class InputIterator, class Predicate>
typename std::iterator_traits<InputIterator>::difference_type USD_count_if(InputIterator first, InputIterator last, Predicate pred)
{
        typename std::iterator_traits<InputIterator>::difference_type n = 0;
        for (; first != last; first++)
        {
                if (pred(*first))
                {
                        n++;
                }
        }
        return n;
}

int main()
{
        int ia[5] = { 1,2,2,2,3 };
        std::vector<int> iv(ia, ia+5);
        std::vector<int>::iterator item = USD_adjacent_find(iv.begin(), iv.end());
        //USD_unique(iv.begin(), iv.end());
        int n = USD_count_if(iv.begin(), iv.end(), compere<int>());
        return 0;
}

此算法通过遍历数据,统计满足条件的数据个数。与count相比,只是将条件封装成了仿函数,可通过仿函数满足自己的条件

17.find 查找某个元素返回一个迭代器

template<class InputIterator,class T>
InputIterator USD_find(InputIterator first, InputIterator last, const T& value)
{
        while (first != last && *first != value)
        {

                ++first;
        }
        return first;
}

int main()
{
        int ia[5] = { 1,2,2,2,3 };
        std::vector<int> iv(ia, ia+5);
        std::vector<int>::iterator item = USD_find(iv.begin(), iv.end(),3);
        return 0;
}

此算法通过遍历数组,不满足条件时继续遍历数据。满足条件时,返回指向这个数据的迭代器

18.find_if 查找某个元素返回一个迭代器

template<class T>
class compere
{
public:
        compere()
        {

        }

        bool operator()(T Value)
        {
                if (Value > 2)
                {
                        return true;
                }
                return false;
        }

};

template<class InputIterator,class Predicate>
InputIterator USD_find_if(InputIterator first, InputIterator last, Predicate pred)
{
        while (first != last && !pred(*first))
        {

                ++first;
        }
        return first;
}

int main()
{
        int ia[5] = { 1,2,2,2,3 };
        std::vector<int> iv(ia, ia+5);
        std::vector<int>::iterator item = USD_find_if(iv.begin(), iv.end(), compere<int>());
        return 0;
}

此算法通过遍历数组,不满足条件时继续遍历数据。满足条件时,返回指向这个数据的迭代器。相比上一个算法,这里将条件封装成了迭代器,用户可自定义条件。

19.find_end 查找完全匹配的子串最后出现的位置

在这里插入图片描述

template<class ForwardIterator1, class ForwardIterator2>
ForwardIterator1 USD_find_end(ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2)
{
        if (first2 == last2)
        {
                return last1;
        }
        else
        {
                ForwardIterator1 result = last1;
                while (1)
                {
                        ForwardIterator2 new_result = USD_search(first1,last1,first2,last2);
                        if (new_result == last1)
                        {
                                return result;
                        }
                        else
                        {
                                result = new_result;
                                first1 = new_result;
                                ++first1;
                        }
                }
        }
}
int main()
{
        int ia[5] = { 1,2,2,2,3 };
        std::vector<int> iv(ia, ia+5);

        std::vector<int> ivec;
        ivec.push_back(2);
        ivec.push_back(2);
        std::vector<int>::iterator item = USD_find_end(iv.begin(), iv.end(), ivec.begin(), ivec.end());

        for (; item != iv.end(); item++)
        {
                printf("%d\n", *item);
        }

        return 0;
}

此函数的核心思想,首先查找子串的位置。若查找到子串,将查找的开始位置移动到此位置的下一个位置。同时记录此位置,如果没查找到,就返回上一个记录的位置。

20.find_first_of 查找目标区的元素在源区第一次出现的位置

template<class InputIterator, class ForwardIterator>
InputIterator USD_find_first_of(InputIterator first1, InputIterator last1, ForwardIterator first2, ForwardIterator last2)
{
        for (; first1 != last1; ++first1)
        {
                for (ForwardIterator iter = first2; iter != last2; ++iter)
                {
                        if (*first1 == *iter)
                        {
                                return first1;
                        }
                }
        }
        return last1;
}

int main()
{
        int ia[5] = { 1,2,3,4,5 };
        std::vector<int> iv(ia, ia+5);

        std::vector<int> ivec;
        ivec.push_back(4);
        ivec.push_back(5);
        std::vector<int>::iterator item = USD_find_first_of(iv.begin(), iv.end(), ivec.begin(), ivec.end());

        for (; item != iv.end(); item++)
        {
                printf("%d\n", *item);
        }

        return 0;
}

此算法由两个for() 循环完成,整体逻辑遍历源区的每一个元素与目标区的每一个元素对比。当第一次满足条件时,返回指向源区的迭代器

21.for_each 遍历数据

template<class InputIterator, class Function>
Function USD_for_each(InputIterator first, InputIterator last, Function f)
{
        for (; first != last; ++first)
        {
                f(*first);
        }
        return f;
}

此算法,主要为遍历数据,处理逻辑存放在仿函数中。通过修改仿函数来达到自己的需求。

22. generate 将仿函数运行的结果填入源区间元素中

template<class ForwardIterator, class Generator>
ForwardIterator USD_generate(ForwardIterator first, ForwardIterator last, Generator gen)
{
        for (; first != last; ++first)
        {
                *first = gen();
        }
        return first;
}

遍历元素,通过仿函数计算的值填入到元素中

23. generate_n 运算结果填写到从迭代器开始的n个元素身上

template<class ForwardIterator,class size, class Generator>
ForwardIterator USD_generate_n(ForwardIterator first, ForwardIterator last, size n, Generator gen)
{
        for (; n>0; --n,++first)
        {
                *first = gen();
        }
        return first;
}

与上一个函数类似,只是控制了填写的个数和开始的位置

24. includes (应用有序区间),验证目标集合是否为源集合的子集

在这里插入图片描述

template<class T>
class USD_less
{
public:
        USD_less()
        {

        }

        bool operator()(T leftValue, T rightValue)
        {
                if (leftValue < rightValue)
                {
                        return true;
                }
                return false;
        }
};

template<class InputIterator1, class InputIterator2,class compare>
bool USD_includes(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, compare comp)
{
        while (first1 != last1 && first2 != last2)
        {
                if (comp(*first2, *first1))
                {
                        return false;
                }
                else if (comp(*first1, *first2))
                {
                        first1++;
                }
                else
                {
                        first1++;
                        first2++;
                }
        }
        return first2 == last2;
}

int main()
{
        int ia[5] = { 1,2,3,4,5 };
        std::vector<int> iv(ia, ia+5);

        std::vector<int> ivec;
        ivec.push_back(4);
        ivec.push_back(5);
        bool bvalue = USD_includes(iv.begin(), iv.end(), ivec.begin(), ivec.end(), USD_less<int>());
        ivec.push_back(6);
        bvalue = USD_includes(iv.begin(), iv.end(), ivec.begin(), ivec.end(), USD_less<int>());
        return 0;
}

遍历集合,将源集合和目标集合取出数据一一对比。源集合数据小于目标集合数据时
,源集合数据查找下一个。当相等时,源集合和目标集合统一下一个数据。当源集合遍历结束时,判断目标集合是否遍历完,若遍历完,则目标集合属于原集合的子集。

25. max_element 返回一个指向最大元素的迭代器

template<class ForwardIterator, class compare>
ForwardIterator USD_max_element(ForwardIterator first, ForwardIterator last, compare comp)
{
        if (first == last)
        {
                return first;
        }
        ForwardIterator result = first;
        while (++first != last)
        {
                if (comp(*result,*first))
                {
                        result = first;
                }
        }
        return result;
}

通过循环查找最大的值,并将结果返回

26. merge(应用有序区间)将两个排序的集合存放在另一个空间中

[图片]

template<class T>
class USD_less
{
public:
        USD_less()
        {

        }

        bool operator()(T leftValue, T rightValue)
        {
                if (leftValue < rightValue)
                {
                        return true;
                }
                return false;
        }
};

template<class InputIterator1, class InputIterator2,class OutputIterator,class compare>
OutputIterator USD_merge(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result, compare comp)
{
        while (first1 != last1 && first2 != last2)
        {
                if (comp(*first1, *first2))
                {
                        *result = *first1;
                        first1++;
                }
                else
                {
                        *result = *first2;
                        first2++;
                }
                result++;
        }
        copy(first1, last1, copy(first2, last2,result));
        return result;
}

int main()
{
        int ia[5] = { 1,2,3,4,5 };
        std::vector<int> iv(ia, ia+5);

        std::vector<int> ivec;
        ivec.push_back(2);
        ivec.push_back(5);
        ivec.push_back(6);
        std::vector<int> vecResult;
        vecResult.resize(8);
        USD_merge(iv.begin(), iv.end(), ivec.begin(), ivec.end(), vecResult.begin(), USD_less<int>());
        return 0;
}

同时遍历两个集合数据,将两个集合中的数据比较,根据满足的条件,分别移动不同集合中的数据。当遍历结束后,其中一个集合必为空集。另外一个集合中剩余的数据,满足放在最后的需求。通过组合使用copy操作,将剩余的数据,拷贝到结果中。

27. min_element 返回一个指向最小值的迭代器

template<class ForwardIterator, class compare>
ForwardIterator USD_min_element(ForwardIterator first, ForwardIterator last, compare comp)
{
        if (first == last)
        {
                return first;
        }
        ForwardIterator result = first;
        while (++first != last)
        {
                if (comp(*result, *first))//result 小于first时,返回true
                {
                        result = first;
                }
        }
        return result;
}

与max_element算法逻辑一样,关键点在于封装的仿函数不同。

28. partition 区间内的集合,判断为true的放前面,判断为false放后面

template<class T>
class USD_LessThan
{
public:
        USD_LessThan()
        {

        }

        bool operator()(T Value)
        {
                if (Value > 4)
                {
                        return true;
                }
                return false;
        }
};

template<class ForwardIterator1, class ForwardIterator2>
void _iter_swap(ForwardIterator1 a, ForwardIterator2 b)
{
        typename std::iterator_traits<ForwardIterator1>::value_type tmp = *a;
        *a = *b;
        *b = tmp;
}

template<class BidircetionalIterator,class Predicate>
BidircetionalIterator USD_partition(BidircetionalIterator first, BidircetionalIterator last, Predicate pred)
{
        while (true)
        {
                while (true)
                {
                        if (first == last)
                        {
                                return first;
                        }
                        if (pred(*first))
                        {
                                ++first;
                        }
                        else
                        {
                                break;
                        }
                }
                --last;
                while (true)
                {
                        if (first == last)
                        {
                                return first;
                        }
                        if (!pred(*last))
                        {
                                --last;
                        }
                        else
                        {
                                break;
                        }
                }
                _iter_swap(first,last);
                ++first;
        }
}

int main()
{
        int ia[9] = { 1,2,3,4,5,6,7,8,9 };
        std::vector<int> iv(ia, ia+9);
        USD_partition(iv.begin(), iv.end(), USD_LessThan<int>());
        return 0;
}
此函数,通过前后遍历数据,从开始端遍历数据,结果为true的移动数据到下一个。结果为false的不移动,与从末端开始逆序遍历的数据,判断结果为true的进行数据交换。即达到预期的效果。

29. remove 删除指定元素(并不删除空间)

template<class InputIterator,class OutputIterator,class T>
OutputIterator USD_remove_copy(InputIterator first, InputIterator last, OutputIterator result, const T& value)
{
        while (first != last)
        {
                if (*first != value)
                {
                        *result = *first;
                        ++result;
                }
                first++;
        }
        return result;
}

template<class ForwardIterator,class T>
ForwardIterator USD_remove(ForwardIterator first, ForwardIterator last, const T& value)
{
        first = std::find(first,last,value);
        ForwardIterator next = first;
        return first == last ? last : USD_remove_copy(++next,last,first, value);
}

int main()
{
        int ia[9] = { 5,2,5,4,5,6,7,5,9 };
        std::vector<int> iv(ia, ia+9);
        USD_remove(iv.begin(), iv.end(),5);
        return 0;
}

此函数,首先通过find找到第一个出现的元素,调用remove_copy,将之后非的删除元素,复制到查找的位置。通过复制粘贴的操作,来达到删除的效果。

30. remove_copy 删除指定元素,结果存放在另外一个空间

template<class InputIterator,class OutputIterator,class T>
OutputIterator USD_remove_copy(InputIterator first, InputIterator last, OutputIterator result, const T& value)
{
        while (first != last)
        {
                if (*first != value)
                {
                        *result = *first;
                        ++result;
                }
                first++;
        }
        return result;
}

通过遍历集合,将不是指定元素的值存放在另一个空间中。

31. remove_if remove_copy_if 删除区间内,被仿函数评估为true的元素

template<class InputIterator,class OutputIterator,class Predicate>
OutputIterator USD_remove_copy_if(InputIterator first, InputIterator last, OutputIterator result, Predicate Pred)
{
        while (first != last)
        {
                if (!Predicate(*first))
                {
                        *result = *first;
                        ++result;
                }
                first++;
        }
        return result;
}

template<class ForwardIterator,class Predicate>
ForwardIterator USD_remove_if(ForwardIterator first, ForwardIterator last, Predicate Pred)
{
        first = std::find_if(first,last,Pred);
        ForwardIterator next = first;
        return first == last ? last : USD_remove_copy_if(++next,last,first, Pred);
}

与之前的函数相比,只是将判断条件封装为了仿函数,来满足用户的需求。

总结

总结出来的这些函数,只占STL算法的一部分,只是用来单纯的数据处理。纵观上述函数内部的实现都很简单,也是日常经常会手动开发的功能。在此进行函数总结,避免日后工作内容的重复开发。后续内容在持续更新中。。。。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2106772.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

hex文件转bin文件

一、简介 在进行MCU开发时,经常需要使用到hex和bin文件,这里总结几种hex转bin的方法。 二、MDK转换 很多的MCU开发,都会用到MDK,而MDK自身是可以执行批处理,来完成hex到bin文件的直接转化的。 见如下指令: fromelf --bin -o ..\..\output\@L.bin #L 这里解释一下上面指令…

音频在线转换mp3:学会这2个方法,拿捏音频转换

如今音频文件的格式转换变得越发重要。你是否曾因为无法在设备上播放特定格式的歌曲而感到困扰&#xff1f;你是否希望将原有的音频文件转换为更常见、更通用的mp3格式&#xff0c;以便在不同设备上畅快地品味音乐&#xff1f; 为了音频文件的顺利播放&#xff0c;我们需要学会…

SpringBoot 增量部署发布

一、背景介绍 由于项目依赖的jar越来越多&#xff0c;Springboot默认的打包方式是将整个项目打包成一个jar包&#xff0c;每次发布时&#xff0c;打包后的jar越来越大&#xff0c;更新一个很小的功能&#xff0c;需要将整个jar上传运行。这样效率太低了&#xff0c;考虑实现每…

2024年百元蓝牙耳机推荐有哪些?四款年度热门机型评测推荐

随着蓝牙技术的不断成熟和普及&#xff0c;蓝牙耳机已经悄然成为我们日常生活中不可或缺的一部分&#xff0c;特别是在2024年&#xff0c;市面上涌现出了许多性价比极高的百元蓝牙耳机&#xff0c;那么在众多的蓝牙耳机里2024年百元蓝牙耳机推荐有哪些&#xff1f;为了解决大家…

【Java】实体类Javabean

文章目录 前言一、实体类Javabean是什么&#xff1f;二、代码总结 前言 记录实体类的基本语法 一、实体类Javabean是什么&#xff1f; 其实就是一种特殊形式的类&#xff0c;这种类特殊点在于&#xff1a; 1、这个类中的成员变量都要私有&#xff0c;并且要对外提供相应的ge…

【STM32+HAL库】---- 硬件IIC驱动0.96OLED

硬件开发板&#xff1a;STM32G0B1RET6 软件平台&#xff1a;cubemaxkeilVScode内容原著声明 代码借鉴学习于以下文章&#xff1a; STM32 使用硬件IIC驱动0.96寸4针IOLED显示器&#xff08;HAL库&#xff09; 1 新建cubemax工程 1.1 配置系统时钟RCC 1.2 配置引脚 1.3 导出工…

ICM20948 DMP代码详解(1)

序言 接触Invensense的芯片这已经是第三次了。2015年在第二空间的时候第一次接触它的芯片&#xff0c;那时候是MPU9250&#xff1b;2021年的时候在智橙动力再一次接触到了MPU6050&#xff0c;那个时候用到了其中的DMP&#xff1b;这次接触的是ICM20948&#xff0c;按目前笔者理…

吃多一时爽,吃少活更长!

美国索尔克生物研究所Belmonte研究团队和中科院研究团队在Cell上发表题为Caloric Restriction Reprograms the Single-Cell Transcriptional Landscape of Rattus Norvegicus Aging的研究内容&#xff0c;比较了摄入热量少30%的老鼠和正常饮食的老鼠之间的区别&#xff0c;发现…

黑马点评7——达人探店

文章目录 发布探店笔记查看探店笔记点赞功能点赞排行榜功能 发布探店笔记 这个其实比较简单&#xff0c;就是把笔记保存到数据库tb_blog中去 PostMappingpublic Result saveBlog(RequestBody Blog blog) {// 获取登录用户UserDTO user UserHolder.getUser();blog.setUserId(u…

python OpenCV的羽化融合图像

1. 读入两幅图像,苹果和橘子 2. 构建苹果和橘子的高斯金字塔&#xff08;6 层&#xff09; 3. 根据高斯金字塔计算拉普拉斯金字塔 4. 在拉普拉斯的每一层进行图像融合&#xff08;苹果的左边与橘子的右边融合&#xff09; 5. 根据融合后的图像金字塔重建原始图像。 impor…

YOLOv5改进 | 模块缝合 | C3 融合REPVGGOREPA提升检测性能【详细步骤 完整代码】

秋招面试专栏推荐 &#xff1a;深度学习算法工程师面试问题总结【百面算法工程师】——点击即可跳转 &#x1f4a1;&#x1f4a1;&#x1f4a1;本专栏所有程序均经过测试&#xff0c;可成功执行&#x1f4a1;&#x1f4a1;&#x1f4a1; 专栏目录 &#xff1a;《YOLOv5入门 改…

数字与文字组合商标,有一个元素近似整体驳回!

经常遇到有网友问驳回复审要不要做复审&#xff0c;其实判断分析好&#xff0c;大多数商标驳回后不值得做复审&#xff0c;也可以省掉不必要的费用&#xff0c;最近有个网友联系到普推知产商标老杨&#xff0c;咨询一个驳回复审的问题。 这个网友的商标是数字和文字组合&#…

若依系统的学习

若依环境 介绍 ‌若依是一款快速开发平台(低代码)&#xff0c;用于快速构建企业级后台管理系统&#xff0c;它提供了许多常用的功能模块和组件&#xff0c;包括权限管理、代码生成、工作流、消息中心等 官方地址: https://www.ruoyi.vip/ ‌基于Spring Boot和Spring Cloud‌…

【分享】Excel表格设置“打开密码”的两种方法

在工作中&#xff0c;Excel文件通常包含敏感数据&#xff0c;出于安全性考虑&#xff0c;给文件设置打开密码是非常有效的方式。接下来&#xff0c;小编给大家介绍两种方法&#xff0c;帮助你轻松为Excel文件设置密码。 方法一&#xff1a;在Excel表里设置“打开密码” 这是Ex…

2024AEI:Cross-Supervised multisource prototypical network

目录 研究动机 研究数据集 研究方法 研究动机 该论文是为了解决以轴承故障诊断为背景的多源域小样本域自适应问题而提出的。文中有提及到实际的工业生产中&#xff0c;存在多源域缺少足够的样本标签数据支撑一般的多源域域自适应&#xff08;MSDA&#xff09;方法的情况&…

借助el-steps和el-form实现超长规则配置的功能

目录 一、应用场景 二、开发流程 三、详细开发流程 四、总结 一、应用场景 最近开发了一个规则类的配置功能&#xff0c;这个功能之前就写过&#xff0c;最近完善了一下&#xff0c;所以将原先的规则变得更多元化&#xff0c;结构也更多了一层&#xff0c;添加新功能的时候…

Java箱与泛型

大O的渐进表示法 大 O 的渐进表示法 去掉了那些对结果影响不大的项 &#xff0c;简洁明了的表示出了执行次数。 void func1(int N){ int count 0; for (int i 0; i < N ; i) { for (int j 0; j < N ; j) { count; } } for (int k 0; k < 2 * N ; k) { count; } in…

深度学习示例2-多输入多输出的神经网络模型

一、代码示例 from tensorflow import keras from tensorflow.keras import layers import numpy as np# 定义 多输入 多输出的模型 vocabulary_size = 1000 num_tags = 100 num_departments = 4title = keras.Input(shape=(vocabulary_size,), name = "title") tex…

【虚拟化】KVM常用命令操作(virsh磁盘管理)

目录 一、KVM概述 1.1 KVM工具栈 1.2 libvirt架构概述 1.3 KVM磁盘格式介绍 1.4 KVM磁盘操作常见语法 1.5 qemu-img命令简介 1.6 libguestfs安装 二、虚拟机磁盘管理 2.1 查看虚拟机磁盘 2.2 创建虚拟机磁盘 2.3 扩容磁盘容量 2.4 查看虚拟机存储状态 2.5 快照 2…

基于BiLSTM-CRF的医学命名实体识别研究(下)模型构建

一.生成映射字典 接下来需要将每个汉字、边界、拼音、偏旁部首等映射成向量。所以&#xff0c;我们首先需要来构造字典&#xff0c;统计多少个不同的字、边界、拼音、偏旁部首等&#xff0c;然后再构建模型将不同的汉字、拼音等映射成不同的向量。 在prepare_data.py中自定义…