算法泛化过程(摘自STL源码剖析)

算法泛化意义

有时存在一些比较底层且常用的算法,这些算法需要被复用,并且应该独立于特定的容器(其实这这也是STL中算法的思想)

算法泛化的关键

1. 将操作对象的类别进行泛化(可以使用模板)

2. 把操作对象的标示法和区间目标的移动行为抽象化

这样就可以使得算法在一个抽象的层面进行工作,从而独立于特定的使用场景

算法泛化过程

以find功能为例,在array中寻找特定值,首先我们实现一个仅仅支持数组的查找算法

int* find(int* array, int size, int value)
{
    for (int i = 0; i < size; ++i)
    {
        if (array[i] == value)
            break;
    }
    return &(array[i]);
}

该算法的大致意思为在array中查找value,若存在value,则返回value所在地址(也就是指针),否则返回最后一个元素的下一个元素的地址(最后一个元素也成为end)。若不常用stl可能觉得返回end非常奇怪,这边明明是可以返回一个nullptr来表示查找无结果。但思考一下一个指向array元素的指针,不但可能合法的指向array内部的元素,其实也可以指向array尾端以外的任何位置(只是这些位置对我们来说没有意义,只是不能对其进行取值,所以在使用时需要判断一下是否为我们想要的值)

但是find使用这种做法使用了容器太多的细节,以至于不能比较好的实现泛化(例如使用size来获取容器中元素的个数)。为了适用于所有类型的容器,其操作应该回更抽象化,可以让find函数接受两个指针作为参数,标示出一个操作区间

int* find(int* begin, int* end, int value)
{
    while(begin != end && *begin != value)
        ++begin;

    return begin;
}

该函数在前闭后开区间[begin, end)(stl中所有区间都是这种表示形式)内查找value并返回指针,指向所找到的第一个符合条件的元素,若没找到则返回end。

到现在为止,find函数只适合int类型容器,所以可以将其增强为一个函数模板(使用模板是实现库函数一个非常好的思想)

template<typename T>
T* find(T* begin, T* end, const T& value)
{
    while(begin != end && *begin != value)
        ++begin;

    return begin;
}

到目前为止,修改后的find()几乎适用于任何允许指针指入的容器。为了打破find只能使用指针的限制,我们可以设计一个类来替代原生指针的行为,并为其实现必要的功能(判断不等,取值,前置递增,复制),修改完的find()如下所示

template<class Iterator, class T>
Iterator find(Iterator begin, Iterator end, const T& value)
{
    while (begin != end, && *begin != value)
        ++begin;

    return begin; // 此处会发生拷贝构造
}

这便是一个完全泛化的find()函数,与任何c++标准库中的长相几乎一模一样。我们在自己实现一些库函数时,可以参考这种写法,来提高自己代码的复用性。以及stl这种数据与算法分离的想法,也值得我们学习。

  • 10
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值