STL标准算法和成员函数算法

本文对比分析了STL容器中成员函数find与非成员函数find在效率和功能上的差异,通过实验证明成员函数find在查找速度上显著优于非成员函数find,并且在功能上提供了更灵活的比较方式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

readme

STL容器算法几乎我们每天都会用,查找一个元素需要用到find,删除一个元素需要用到erase和remove,统计需要用到accumulate或for_each等等。许多算法有两种版本,一种是容器自己的成员函数,例如vector, set都有自己的find成员函数;另一种是通用的非成员函数,例如STL标准算法也有find函数,可以完成vector和set容器中的查找工作。这篇博客以set容器和find算法为例,从效率和功能两方面对比了两种版本算法之间的差别。

效率方面

成员函数find和非成员函数find之间的关系很像量产和定制。一件量产商品通常追求销量,要满足尽可能更多用户的需求,这也意味着这件商品通常不会致力于每个用户都百分百满意。而定制商品不同,它们追求让小部分用户得到极致的满足,而在必要时放弃考虑大多数用户的需求。
有点扯远了,LOL~~。不过话糙理不糙,set容器的成员函数find,就像是为set定制的一样,它清楚set内部使用了红黑树结构,它的复杂度是对数级别的。而非成员函数find并没有做这种定制,因为它同时要服务vector,set,list等容器,它只能一个一个的找。虽然这两种版本都是为了找到set容器中是否存在某个元素,但是当元素数量较大时,这种效率差异就会非常明显。

功能方面

之前有写过一篇博客介绍“相等”和“等价”之间的差别,在这里又用上了。还是相同的道理,非成员函数find同时要服务vector,set,list等容器,它判断元素是否存在的底层技术是“相等”。而set成员函数find用到的底层技术是“等价”,set容器还允许用户自定义一个比较判别式,set成员函数find会用到这个比较判别式。
基于上述事实,两种版本的find函数所做的事情又不尽相同,因为它们判断的方法不一样,一个用的是是否“相等”,另一个用的是可以定制化的是否“等价”。

测试程序

//common.h
#ifndef _COMMON_H_
#define _COMMON_H_

#include <string>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <iostream>
#include <utility>
#include <algorithm>
#include <vector>
#include <iterator>
#include <sys/time.h>

using namespace std;
#endif
//Timer.h
#ifndef _TIMER_H
#define _TIMER_H

#include <sys/time.h>
#include "common.h"

class Timer
{
public:
    Timer(string strCallInfo = "Timer", bool us_need = false)
    {
        _desc = strCallInfo;
        _us_need = us_need;
        gettimeofday(&_begin, NULL);
        gettimeofday(&_end, NULL);
    };

    ~Timer()
    {
        gettimeofday(&_end,NULL);
        printf("%s, cost %ldms\n", _desc.c_str(), (_end.tv_sec - _begin.tv_sec) * 1000 + (_end.tv_usec - _begin.tv_usec) / 1000);
        if (_us_need)
        {
            printf("%s, cost %ldus\n", _desc.c_str(), (_end.tv_sec - _begin.tv_sec) * 1000000 + _end.tv_usec - _begin.tv_usec);
        }
    };
private:
    Timer(){};
    string  _desc;
    bool _us_need;

    timeval _begin;
    timeval _end;
};

#endif
//member_vs_nonmember.cpp
#include "common.h"
#include "Timer.h"

struct Aastrcmp:public binary_function<string, string, bool>
{
    bool operator()(const string& str1, const string& str2)
    {
        return strcasecmp(str1.c_str(), str2.c_str());
    }
};

int main(void)
{
    set<int> testSetInt;
    for (int i = 0; i < 10000; ++i)
    {
        testSetInt.insert(i);
    }

    vector<int> intVector;
    intVector.reserve(10000);
    for (int i = 0; i < 10000; ++i)
    {
        intVector.push_back(i + 5000);
    }

    {
        Timer timer("non-member function find cost");
        for (int i = 0; i < 10000; ++i)
        {
            find(testSetInt.begin(), testSetInt.end(), intVector[i]);
        }
    }

    {
        Timer timer("member function find cost");
        for (int i = 0; i < 10000; ++i)
        {
            testSetInt.find(intVector[i]);
        }
    }

    set<string, Aastrcmp> testSetStr;
    testSetStr.insert("Abcd");
    testSetStr.insert("abcd");
    if (find(testSetStr.begin(), testSetStr.end(), "ABCD") == testSetStr.end())
    {
        printf("ABCD not found by non_member function find\n");
    }
    else
    {
        printf("ABCD found by non_member function find\n");
    }

    if (testSetStr.find("ABCD") == testSetStr.end())
    {
        printf("ABCD not found by member function find\n");
    }
    else
    {
        printf("ABCD found by member function find\n");
    }
}

编译和执行结果

g++ -o member_vs_nonmember member_vs_nonmember.cpp -O0 -g -Wall -std=c++11
./member_vs_nonmember 
non-member function find cost, cost 1012ms
member function find cost, cost 2ms
ABCD not found by non_member function find
ABCD found by member function find

测试程序说明

效率方面,可以从打印信息直观的看到,两个版本的find算法效率差了不止一个数量级。功能方面,两个版本的find算法得到的结论也不一致。综上,大多数场景下,推荐优先考虑成员函数版本的算法。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值