VC++调用STL算法函数有效提升STL列表的搜索速度(附源码)

Posted dvlinker

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了VC++调用STL算法函数有效提升STL列表的搜索速度(附源码)相关的知识,希望对你有一定的参考价值。

       STL(Standard Templete Library)活动模板库已被广泛地应用于各种C++程序的开发中,STL中vector、list、map等列表极大地方便了我们日常的开发,不再需要我们去实现链表等数据结构,使用这些列表能基本能解决开发过程中遇到的各种问题。网上关于STL的文章比较多,今天我们就来说说在存放大量数据时我们该如何提升STL列表搜索速度

1、概述

       当vector、list等STL列表中存放的数据量比较大时,去遍历列表去搜索,效率就是个问题了。如果只是简单地使用for循环去遍历STL列表搜索,速度可能会很慢,一般很难达到快速搜索的要求。那有没有什么办法能有效提升STL的搜索速度呢?答案是肯定的,可以调用STL库的算法函数去进行STL列表的搜索,能够明显提升STL列表的搜索速度。STL库自带的算法函数有conutcount_iffindfind_ifremove_copyremove_copy_if等。这些STL算法函数的详细说明可以参见《STL源码剖析》一书的第6章。

       本文将详细讲述使用STL算法函数find_if和remove_copy_if有效提升搜索速度的范例,给大家提供一个参考。

2、使用find_if搜索单个元素

       有时我们需要通过一个id关键字段到STL列表中搜索对应元素的信息。假设有如下设备信息结构体TDeviceInfo,存放整个设备列表信息的是vector列表vtDevList:

// 设备信息
struct TDeviceInfo 

    char* achDeviceId[64];   // 设备id
    char* achDeviceName[64]; // 设备名称
    int nDevType;            // 设备类型
;

vector<TDeviceInfo> vtDevList; // 存放设备信息的列表

我们由设备id去到vector列表中找对应的设备信息。直接通过for循环去遍历搜索的代码如下:

char* pTargetId = "E40CF3E4-CC2B-437F-A4B9-65F2D5BD0712";

// 通过for循环去遍历列表搜目标设备
vector<TDeviceInfo>::iterator itor = vtDevList.begin();
for ( ; itor != vtDevList.end(); itor++ )

    if ( strcmp(pTargetId, itor->achDeviceId) == 0 )
    
        // 找到目标设备
        break;
    

上述代码通过设备id去找对应的设备信息,是单个设备信息。

       我们可以使用find_if算法函数对上述代码进行改进,代码如下:

char* pTarget = "E40CF3E4-CC2B-437F-A4B9-65F2D5BD0712";

vector<TDeviceInfo>::iterator itor = std::find_if(vtDevList.begin(), vtDevList.end(), 
[&](TDeviceInfo tInfo)  return strcmp(pTarget, tInfo.achDeviceId)==0;  );
if (itor != vtDevList.end())

    // 找到目标设备

使用find_if算法函数可以明显提升搜索的速度。此外,上述函数中使用了C++11中的匿名函数,匿名函数是个好东西,很好用!

3、使用remove_copy_if搜索满足搜索条件的多个元素

       我们有时需要到STL列表去搜索满足搜索条件的多个元素。比如我们要到设备列表中去搜索所有包含“东城区”字样的所有设备信息,使用for循环去遍历的代码如下:

// 通过for循环去遍历列表搜目标设备
char* pMatchNameStr = "东城区";
vector<TDeviceInfo> vtMatchedDevList; // 存放满足匹配条件的元素
vector<TDeviceInfo>::iterator itor = vtDevList.begin();
for (; itor != vtDevList.end(); itor++)

    CStringA strDeviceName = itor->achDeviceName;
    if (strDeviceName.Find(strDeviceName) != -1)
    
        vtMatchedDevList.push_back(*itor);
    

当设备列表vtDevList中存放了数万个元素时,上述for循环搜索的效率就不太高了,我们可以通过使用remove_copy_if算法函数去对现有代码进行替换

BOOL MatchDeviceFunc(TDeviceInfo& tInfo)

	char* pMatchNameStr = "东城区";

	CStringA strDeviceName = tInfo.achDeviceName;
	if ( strDeviceName.Find(pMatchNameStr) != -1 )
	
		return TRUE;
	

	return FALSE;


vector<TDeviceInfo> vtMatchedDevList;
std::remove_copy_if(vtDevList.begin(), vtDevList.end(), std::back_inserter(vtMatchedDevList), &MatchDeviceFunc);

对于上述remove_copy_if调用,前两个参数指明搜索开始和结束的迭代器,第三个元素指定存放满足搜索条件的元素的列表,第四个参数指定条件判断函数MatchDeviceFunc。

       remove_copy_if算法函数的调用,可以有效地提升搜索速度。在我们项目中做过类似这样的优化,搜索速度可以提升1到2个数量级。

4、总结

       在我们搜索STL列表速度遇到瓶颈时,可以考虑使用STL自带的算法函数去有效提升搜索效率。其实我们以前对比过STL算法函数内部的实现,很多STL算法函数内部实现和我们直接去通过for循环遍历的代码是类似的,甚至是一模一样的,比如find_if算法函数的实现,那为啥使用算法函数时就是要快很多呢?可能是编译器能对算法函数中的代码进行更好的优化,使其在运行时能跑的更快一点。

以上是关于VC++调用STL算法函数有效提升STL列表的搜索速度(附源码)的主要内容,如果未能解决你的问题,请参考以下文章

C++中STL学习笔记——常见算法操作演示

C++中STL学习笔记——常见算法操作演示

STL 算法中函数对象和谓词

STL 算法的反向迭代

STL算法中函数对象和谓词

STL_算法_06_遍历算法