非变动性算法代码分析与示例:

一、for_each

C++ Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
 
// TEMPLATE FUNCTION for_each
template < class _InIt,
         class _Fn1 > inline
_Fn1 for_each(_InIt _First, _InIt _Last, _Fn1 _Func)
{
    // perform function for each element
    _DEBUG_RANGE(_First, _Last);
    _DEBUG_POINTER(_Func);
    _CHECKED_BASE_TYPE(_InIt) _ChkFirst(_CHECKED_BASE(_First));
    _CHECKED_BASE_TYPE(_InIt) _ChkLast(_CHECKED_BASE(_Last));
    for (; _ChkFirst != _ChkLast; ++_ChkFirst)
        _Func(*_ChkFirst);
    return (_Func);
}

函数以模板实现,_Inlt 即 iterator 类型,_Fn1 是函数指针,函数体内首先判断迭代器是否在范围内以及传递的第三个参数是否是函

数指针,接下去两行实际上就是定义两个临时的迭代器,相当于 _Inlt  ChkFirst(_First); 在遍历的过程中将每个容器元素取出并当作参

数传递给函数指针,即 _Func(*ChkFirst);  for_each 函数返回值是函数指针

二、max_element、min_element

两个函数实现差不多,只看min_element:

C++ Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 

// TEMPLATE FUNCTION min_element
template<class _FwdIt> inline
_FwdIt _Min_element(_FwdIt _First, _FwdIt _Last)
{
    // find smallest element, using operator<
    _DEBUG_RANGE(_First, _Last);
    _FwdIt _Found = _First;
    if (_First != _Last)
        for (; ++_First != _Last; )
            if (_DEBUG_LT(*_First, *_Found))
                _Found = _First;
    return (_Found);
}

template<class _FwdIt> inline
_FwdIt min_element(_FwdIt _First, _FwdIt _Last)
{
    // find smallest element, using operator<
    _ASSIGN_FROM_BASE(_First,
                      _Min_element(_CHECKED_BASE(_First), _CHECKED_BASE(_Last)));
    return (_First);
}

首先  #define _ASSIGN_FROM_BASE(_Dest, _Src)  _Dest = (_Src) 即将_Min_element 函数的返回值复制给_First,而在

_Min_element 函数内就是遍历容器,不断保存最小元素的位置,其中 #define _DEBUG_LT(x, y) ((x) < (y))   故

_DEBUG_LT(*_First, *_Found) 也就是取出元素比较大小,返回最后保存的最小元素位置。

实际上min_element 还重载了另一个函数模板:

C++ Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
 
template < class _FwdIt,
         class _Pr > inline
_FwdIt _Min_element(_FwdIt _First, _FwdIt _Last, _Pr _Pred)
{
    // find smallest element, using _Pred
    _DEBUG_RANGE(_First, _Last);
    _DEBUG_POINTER(_Pred);
    _FwdIt _Found = _First;
    if (_First != _Last)
        for (; ++_First != _Last; )
            if (_DEBUG_LT_PRED(_Pred, *_First, *_Found))
                _Found = _First;
    return (_Found);
}

template < class _FwdIt,
         class _Pr > inline
_FwdIt min_element(_FwdIt _First, _FwdIt _Last, _Pr _Pred)
{
    // find smallest element, using _Pred
    _ASSIGN_FROM_BASE(_First,
                      _Min_element(_CHECKED_BASE(_First), _CHECKED_BASE(_Last), _Pred));
    return (_First);
}

主要的区别只是在于这个版本可以自定义进行比较,比如如果容器内不是装着数值元素,而是string 或者其他类型,也许它们没有重

载 operator<,可以自定义一个函数对它们进行比较大小,如 #define _DEBUG_LT_PRED(pred, x, y) pred(x, y) 就是这个意思。

三、find、find_if

C++ Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
 
// TEMPLATE FUNCTION find
template<class _InIt, class _Ty>
inline
_InIt _Find(_InIt _First, _InIt _Last, const _Ty &_Val)
{
    // find first matching _Val
    _DEBUG_RANGE(_First, _Last);
    for (; _First != _Last; ++_First)
        if (*_First == _Val)
            break;
    return (_First);
}

template<class _InIt, class _Ty>
inline
_InIt find(_InIt _First, _InIt _Last, const _Ty &_Val)
{
    // find first matching _Val
    _ASSIGN_FROM_BASE(_First,
                      _Find(_CHECKED_BASE(_First), _CHECKED_BASE(_Last), _Val));
    return (_First);
}

// TEMPLATE FUNCTION find_if
template < class _InIt,
         class _Pr > inline
_InIt _Find_if(_InIt _First, _InIt _Last, _Pr _Pred)
{
    // find first satisfying _Pred
    _DEBUG_RANGE(_First, _Last);
    _DEBUG_POINTER(_Pred);
    for (; _First != _Last; ++_First)
        if (_Pred(*_First))
            break;
    return (_First);
}

template < class _InIt,
         class _Pr > inline
_InIt find_if(_InIt _First, _InIt _Last, _Pr _Pred)
{
    // find first satisfying _Pred
    _ASSIGN_FROM_BASE(_First,
                      _Find_if(_CHECKED_BASE(_First), _CHECKED_BASE(_Last), _Pred));
    return (_First);
}

里面很多宏跟前面函数出现的是一样的,find 就是遍历容器,找出与Val 相等的第一个元素位置,函数返回迭代器 。

find_if 则可以自定义查找,不一定是与某值相等,也可以其他比较如大于小于等,如if (_Pred(*_First))  如果_Pred 函数返回为真

则break,至于_Pred 怎样实现就不关find_if 的事了。

示例代码1:

C++ Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
 
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

void print_element(int n)
{
    cout << n << ' ';
}

bool greater_than_3(int n)
{
    return n > 3;
}

int main(void)
{
    int a[] = { 1, 2, 3, 4, 5 };
    vector<int> v(a, a + 5);

vector<int>::const_iterator it;
    for (it = v.begin(); it != v.end(); ++it)
        cout << *it << ' ';
    cout << endl;

for_each(v.begin(), v.end(), print_element);
    cout << endl;

for (it = v.begin(); it != v.end(); ++it)
        cout << *it << ' ';
    cout << endl;

it = min_element(v.begin(), v.end());
    if (it != v.end())
    {
        cout << *it << endl;
    }

it = max_element(v.begin(), v.end());
    if (it != v.end())
    {
        cout << *it << endl;
    }

it = find(v.begin(), v.end(), 3);
    if (it != v.end())
    {
        cout << it - v.begin() << endl;
    }
    else
        cout << "not found" << endl;

it = find_if(v.begin(), v.end(), greater_than_3);
    if (it != v.end())
    {
        cout << it - v.begin() << endl;
    }
    else
        cout << "not found" << endl;

return 0;
}

C++ Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
 
// TEMPLATE FUNCTION search
template < class _FwdIt1,
         class _FwdIt2,
         class _Diff1,
         class _Diff2 > inline
_FwdIt1 _Search(_FwdIt1 _First1, _FwdIt1 _Last1,
                _FwdIt2 _First2, _FwdIt2 _Last2, _Diff1 *, _Diff2 *)
{
    // find first [_First2, _Last2) match
    _DEBUG_RANGE(_First1, _Last1);
    _DEBUG_RANGE(_First2, _Last2);
    _Diff1 _Count1 = 0;
    _Distance(_First1, _Last1, _Count1);
    _Diff2 _Count2 = 0;
    _Distance(_First2, _Last2, _Count2);

for (; _Count2 <= _Count1; ++_First1, --_Count1)
    {
        // room for match, try it
        _FwdIt1 _Mid1 = _First1;
        for (_FwdIt2 _Mid2 = _First2; ; ++_Mid1, ++_Mid2)
            if (_Mid2 == _Last2)
                return (_First1);
            else if (!(*_Mid1 == *_Mid2))
                break;
    }
    return (_Last1);
}

template < class _FwdIt1,
         class _FwdIt2 > inline
_FwdIt1 search(_FwdIt1 _First1, _FwdIt1 _Last1,
               _FwdIt2 _First2, _FwdIt2 _Last2)
{
    // find first [_First2, _Last2) match
    _ASSIGN_FROM_BASE(_First1,
                      _Search(_CHECKED_BASE(_First1), _CHECKED_BASE(_Last1),
                              _CHECKED_BASE(_First2), _CHECKED_BASE(_Last2),
                              _Dist_type(_First1), _Dist_type(_First2)));
    return _First1;
}

函数传入4个迭代器,假设前两个迭代器指示的位置有10个元素,后两个迭代器指示的位置有2个元素,如果在第一个区间能够找到

完全匹配第二个区间的元素,则返回起始位置,如果不能则返回Last1,即第一个区间末尾,注意必须顺序匹配2个元素,也可以看

成在第一个区间寻找第一次出现的第二个区间子段。

函数的实现也不难理解,双重循环,比如首先比较L1[0] 与 L2[0] , 如果相等再比较L1[1] 与 L2[1]; 如果不等则移动,从L1[1] 开始比

较,假设L1[4], L1[5] 与L2[0], L2[1] 完全匹配,则返回值是指向L1[4] 的 iterator。

此外seach 也重载了另一个版本,可以自定义比较,代码比较长且跟上面重复较多就不贴了,主要的变化就是将上面24行的代码

换成 else if (!_Pred(*_Mid1, *_Mid2)) 也就是自定义比较逻辑。

下面贴一个MSDN 的例子:

C++ Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
 
// alg_search.cpp
// compile with: /EHsc
#include <vector>
#include <list>
#include <algorithm>
#include <iostream>

// Return whether second element is twice the first
bool twice (int elem1, int elem2 )
{
    return 2 * elem1 == elem2;
}

int main( )
{
    using namespace std;
    vector <int> v1, v2;
    list <int> L1;
    vector <int>::iterator Iter1, Iter2;
    list <int>::iterator L1_Iter, L1_inIter;

int i;
    for ( i = 0 ; i <= 5 ; i++ )
    {
        v1.push_back( 5 * i );
    }
    for ( i = 0 ; i <= 5 ; i++ )
    {
        v1.push_back( 5 * i );
    }

int ii;
    for ( ii = 4 ; ii <= 5 ; ii++ )
    {
        L1.push_back( 5 * ii );
    }

int iii;
    for ( iii = 2 ; iii <= 4 ; iii++ )
    {
        v2.push_back( 10 * iii );
    }

cout << "Vector v1 = ( " ;
    for ( Iter1 = v1.begin( ) ; Iter1 != v1.end( ) ; Iter1++ )
        cout << *Iter1 << " ";
    cout << ")" << endl;

cout << "List L1 = ( " ;
    for ( L1_Iter = L1.begin( ) ; L1_Iter != L1.end( ) ; L1_Iter++ )
        cout << *L1_Iter << " ";
    cout << ")" << endl;

cout << "Vector v2 = ( " ;
    for ( Iter2 = v2.begin( ) ; Iter2 != v2.end( ) ; Iter2++ )
        cout << *Iter2 << " ";
    cout << ")" << endl;

// Searching v1 for first match to L1 under identity
    vector <int>::iterator result1;
    result1 = search (v1.begin( ), v1.end( ), L1.begin( ), L1.end( ) );

if ( result1 == v1.end( ) )
        cout << "There is no match of L1 in v1."
             << endl;
    else
        cout << "There is at least one match of L1 in v1"
             << "\n and the first one begins at "
             << "position " << result1 - v1.begin( ) << "." << endl;

// Searching v1 for a match to v2 under the binary predicate twice
    vector <int>::iterator result2;
    result2 = search  (v1.begin( ), v1.end( ), v2.begin( ), v2.end( ), twice );

if ( result2 == v1.end( ) )
        cout << "There is no match of L1 in v1."
             << endl;
    else
        cout << "There is a sequence of elements in v1 that "
             << "are equivalent\n to those in v2 under the binary "
             << "predicate twice\n and the first one begins at position "
             << result2 - v1.begin( ) << "." << endl;
}

/*
Vector v1 = ( 0 5 10 15 20 25 0 5 10 15 20 25 )
List L1 = ( 20 25 )
Vector v2 = ( 20 30 40 )
There is at least one match of L1 in v1
and the first one begins at position 4.
There is a sequence of elements in v1 that are equivalent
to those in v2 under the binary predicate twice
and the first one begins at position 2.
*/

参考:

C++ primer 第四版
Effective C++ 3rd
C++编程规范

转载于:https://www.cnblogs.com/alantu2018/p/8471418.html

非变动性算法源代码分析与使用示例( for_each、min_element 、find_if、search 等)...相关推荐

  1. 变动性算法源代码分析与使用示例(copy_backward、 transform、 replace_copy_if 等)

    首先回顾前面的文章,我们把for_each 归类为非变动性算法,实际上它也可以算是变动性算法,取决于传入的第三个参数,即函数 指针.如果在函数内对容器元素做了修改,那么就属于变动性算法. 变动性算法源 ...

  2. 从零开始学C++之STL(七):剩下5种算法代码分析与使用示例(remove 、rotate 、sort、lower_bound、accumulate)...

    一.移除性算法 (remove) C++ Code  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 2 ...

  3. 从零开始学C++之STL(七):剩下5种算法代码分析与使用示例(remove 、rotate 、sort、lower_bound、accumulate)

    一.移除性算法 (remove) C++ Code  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 2 ...

  4. Java 理论与实践: 非阻塞算法简介——看吧,没有锁定!(转载)

    简介: Java™ 5.0 第一次让使用 Java 语言开发非阻塞算法成为可能,java.util.concurrent 包充分地利用了这个功能.非阻塞算法属于并发算法,它们可以安全地派生它们的线程, ...

  5. Java 理论与实践: 非阻塞算法简介

    在不只一个线程访问一个互斥的变量时,所有线程都必须使用同步,否则就可能会发生一些非常糟糕的事情.Java 语言中主要的同步手段就是 synchronized 关键字(也称为内在锁),它强制实行互斥,确 ...

  6. Java 理论与实践: 非阻塞算法简介--转载

    在不只一个线程访问一个互斥的变量时,所有线程都必须使用同步,否则就可能会发生一些非常糟糕的事情.Java 语言中主要的同步手段就是synchronized 关键字(也称为内在锁),它强制实行互斥,确保 ...

  7. 【Java 虚拟机原理】垃圾回收算法 ( 可达性分析算法 | GC Root 示例 | GC 回收前的两次标记 | finalize 方法示例 )

    文章目录 一.可达性分析算法 二.GC Root 示例 三.GC 回收前的两次标记 四.finalize 方法示例 一.可达性分析算法 在 堆内存 中 , 存在一个 根对象 GC Root , GC ...

  8. 区块链教程Fabric1.0源代码分析流言算法Gossip服务端二

    区块链教程Fabric1.0源代码分析流言算法Gossip服务端二 Fabric 1.0源代码笔记 之 gossip(流言算法) #GossipServer(Gossip服务端) 5.2.commIm ...

  9. gossip 区块链_区块链教程Fabric1.0源代码分析流言算法Gossip服务端一兄弟连区块链教程-阿里云开发者社区...

    区块链教程Fabric1.0源代码分析流言算法Gossip服务端一,2018年下半年,区块链行业正逐渐褪去发展之初的浮躁.回归理性,表面上看相关人才需求与身价似乎正在回落.但事实上,正是初期泡沫的渐退 ...

最新文章

  1. Rstudio查看关联的R
  2. .NET MVC对接POLYV——HTML5播放器播放加密视频
  3. js检测是否安装了flash插件
  4. ThinkPHP多次重复提交问题的根源
  5. 全栈深度学习第6期: 模型测试和部署
  6. 寻宝机器人电路板焊接_专业维修淮安市KUKA库卡KRC2机器人回收{机器人调试}
  7. 【机器学习笔记之六】Bagging 简述
  8. .NET四种注释规范
  9. 【2021牛客暑期多校训练营9】E Eyjafjalla (倍增,dfs序,主席树)
  10. Java高级工程师需要掌握哪些核心点?
  11. 简约大气昼夜双色导航主题模板/WordPress导航主题模板
  12. 【解决方案】ArcGIS License Manager启动失败
  13. IEEEtran模板使用Bibtex插入DOI不显示问题
  14. TensorFlow Session 中关于 GPU 的配置项解析 ——转自 慢慢学TensorFlow 微信公众号
  15. 三年前,我差点成了爬虫大师
  16. 肯德尔秩相关系数matlab,常用的特征选择方法之 Kendall 秩相关系数
  17. 中山大学计算机学院交换生去国外,中山大学取消与伯克利大学交换生项目
  18. UE4加载Excel表格CSV数据及解决中文乱码问题
  19. PC ACCESS 测试客户机出现错误 win7 64位
  20. list添加元素_如何给List集合的每个元素添加index序号

热门文章

  1. python代码大全p-python处理写入数据代码讲解
  2. python好学吗mooc中文网-Python全栈工程师
  3. 风云编程python-首页
  4. python爬虫项目-32个Python爬虫项目让你一次吃到撑
  5. RxJava响应式编程学习笔记
  6. 数据库数据满足树结构时,求一个结点的子结点有哪些
  7. LeetCode Copy List with Random Pointer
  8. kafka概述与下一代消息队列
  9. vue组件的基本使用,以及组件之间的基本传值方式
  10. 安装 Cacti 监控