/*
2015-06-06 本文主要叙述对于vector<T*> (指针数组)如何进行find 操作下面的代码实现了Find,FindRange 模板函数,
解释了为什么std::find 不能解决问题,
解释了如用find_if来解决问题。
并提供了一个sort 的例子
*/

//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop #include "Unit1.h"
#include <vector>
#include <algorithm>
using namespace std;
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1; class CA
{
public:
int a; CA(int a)
{
this->a = a;
} bool operator == (int t)
{
return a == t;
}
//无法编译
//friend bool operator == (const CA* ca,int t);
};
//无法编译
/*
bool operator == (const CA* ca,int t)
{
return ca->a == t;
}*/ bool Compare(CA* f, CA* s)
{
return f->a < s->a;
} template<class T1,class T2>
vector<T1*>::iterator Find( vector<T1*>::iterator begin,
vector<T1*>::iterator end,
const T2& var)
{
while(begin != end)
{
if (*(*begin) == var)
{
return begin;
}
begin++;
}
} template<class T1,class T2>
vector<T1*> FindRange( vector<T1*>::iterator begin,
vector<T1*>::iterator end,
const T2& var)
{
vector<T1*> result;
while(begin != end)
{
if (*(*begin) == var)
{
result.push_back(*begin);
}
begin++;
}
return result;
} /***
* 使用find_if
*/
static int globA = ; bool prec (CA* ca)
{
if (globA == ca->a)
return true;
else
return false;
} vector<CA*> arry;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
arry.push_back(new CA());
arry.push_back(new CA());
arry.push_back(new CA());
arry.push_back(new CA());
arry.push_back(new CA());
arry.push_back(new CA());
arry.push_back(new CA());
}
//--------------------------------------------------------------------------- void __fastcall TForm1::Button1Click(TObject *Sender)
{
sort(arry.begin(),arry.end(),Compare);
for(unsigned i = ; i < arry.size(); i++)
{
ShowMessage(IntToStr(arry[i]->a));
} vector<CA*>::iterator itor = find(arry.begin(),arry.end(),);
if (itor != arry.end())
{
ShowMessage("find!");
} vector<CA*> range = FindRange<CA,int>(arry.begin(),arry.end(),);
ShowMessage("find "+IntToStr(range.size())+" number"); globA = ;
vector<CA*>::iterator itor2 = find_if(arry.begin(),arry.end(),prec);
if (itor2 != arry.end())
{
ShowMessage("find!");
}
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormDestroy(TObject *Sender)
{
for (unsigned i =; i < arry.size() ;i++)
{
delete arry[i];
arry[i] = NULL;
}
arry.clear();
}
//---------------------------------------------------------------------------

上述代码使用模板函数对vector<T*> 类的数组,进行查找。

标准库中的find 比较的方式如下:

template <class _RandomAccessIter, class _Tp>
_STLP_INLINE_LOOP _RandomAccessIter __find(_RandomAccessIter __first, _RandomAccessIter __last,
const _Tp& __val,
const random_access_iterator_tag &)
{
_STLP_DIFFERENCE_TYPE(_RandomAccessIter) __trip_count = (__last - __first) >> ; for ( ; __trip_count > ; --__trip_count) {
if (*__first == __val) return __first; //解除引用然后比较
++__first; if (*__first == __val) return __first;
++__first; if (*__first == __val) return __first;
++__first; if (*__first == __val) return __first;
++__first;
} switch(__last - __first) {
case :
if (*__first == __val) return __first;
++__first;
case :
if (*__first == __val) return __first;
++__first;
case :
if (*__first == __val) return __first;
++__first;
case :
default:
return __last;
}
}

可以看见,标准库的实现是 *__first == __val ,要求实现 == 操作符。

然而,由于vector<T*> 内的元素都是指针,是无论如何也无法 满足==操作符比较的。

至于,为什么vector里面存指针?这关系到运行效率,指针拷贝成本低。

因此,如果vector<T*>这样的数组,基本考虑2种方式find

//自己实现一个Find泛型方法,不过依然要求实现操作符重载。
template<class T1,class T2>
vector<T1*>::iterator Find( vector<T1*>::iterator begin,
vector<T1*>::iterator end,
const T2& var)
{
while(begin != end)
{
if (*(*begin) == var)
{
return begin;
}
begin++;
}
}

或者采用find_if

template <class _RandomAccessIter, class _Predicate>
_STLP_INLINE_LOOP _RandomAccessIter __find_if(_RandomAccessIter __first, _RandomAccessIter __last,
_Predicate __pred,
const random_access_iterator_tag &)
{
_STLP_DIFFERENCE_TYPE(_RandomAccessIter) __trip_count = (__last - __first) >> ; for ( ; __trip_count > ; --__trip_count) {
if (__pred(*__first)) return __first;
++__first; if (__pred(*__first)) return __first;
++__first; if (__pred(*__first)) return __first;
++__first; if (__pred(*__first)) return __first;
++__first;
} switch(__last - __first) {
case :
if (__pred(*__first)) return __first;
++__first;
case :
if (__pred(*__first)) return __first;
++__first;
case :
if (__pred(*__first)) return __first;
// ++__first; 我不知道为什么这里有这样的注释,C++ BUILDER 6 里面的代码就是这样的。可见,标准库也是人写的。
case :
default:
return __last;
}
}

从find_if 的实现可以看出,他的想法是传入一个类或者函数,把元素作为参数代入,如果函数返回true,就满足条件。

因此,使用了一个全局变量(实际应酌情考虑使用类成员)。

/***
* 使用find_if
*/
static int globA = ; bool prec (CA* ca)
{
if (globA == ca->a)
return true;
else
return false;
}
//使用时
globA = 1;
vector<CA*>::iterator itor2 = find_if(arry.begin(),arry.end(),prec);

附带一个sort排序的例子(这个方式和C#,Java 里的方式差不多,只不过 C# 和Java要求传入的是实现ICompare的接口而已,这里是函数指针,本质都是将“行为”传进去)

在元素遍历,查找,排序方面,C#和Java要优雅的多。也许C++11 解决了这个问题,没去研究了。

C++ 中对vector<T*> 数组的查找和排序的更多相关文章

  1. [转]STL中vector转数组(实际是数组的指针)

    感谢:http://topic.csdn.net/t/20050429/20/3976956.html 感谢:http://yzyanchao.blogbus.com/logs/47796444.ht ...

  2. 转:用STL中的vector动态开辟二维数组

    用STL中的vector动态开辟二维数组 源代码:#include <iostream>#include <vector>using namespace std;int mai ...

  3. Java中数组二分法查找

    算法:当数组的数据量很大适宜采用该方法.采用二分法查找时,数据需是有序不重复的,如果是无序的也可通过选择排序.冒泡排序等数组排序方法进行排序之后,就可以使用二分法查找. 基本思想:假设数据是按升序排序 ...

  4. javascript中的Array对象 —— 数组的合并、转换、迭代、排序、堆栈

    Array 是javascript中经常用到的数据类型.javascript 的数组其他语言中数组的最大的区别是其每个数组项都可以保存任何类型的数据.本文主要讨论javascript中数组的声明.转换 ...

  5. 161101、在Java中如何高效判断数组中是否包含某个元素

    如何检查一个数组(无序)是否包含一个特定的值?这是一个在Java中经常用到的并且非常有用的操作.同时,这个问题在Stack Overflow中也是一个非常热门的问题.在投票比较高的几个答案中给出了几种 ...

  6. JS数组2(冒泡排列、数组里面查找数据)

    数组 一.冒泡排列 对数组attr = [1,8,6,4,5,3,7,2,9]进行由大到小排列,用冒泡排列的方法排列时,会对数组进行比较互换.如果前一个数字较大,这2个元素排列方式不变,如果后一个元素 ...

  7. C++中,申请字符串数组可用new实现

    C++中,申请字符串数组可用new实现: char ** list = new char*[MAX_NUM]; for (int i = 0; i< MAX_LOOP; i++) list[i] ...

  8. 【转】java.util.vector中的vector的详细用法

    [转]java.util.vector中的vector的详细用法 ArrayList会比Vector快,他是非同步的,如果设计涉及到多线程,还是用Vector比较好一些 import java.uti ...

  9. java.util.vector中的vector的详细用法

    ArrayList会比Vector快,他是非同步的,如果设计涉及到多线程,还是用Vector比较好一些 import java.util.*; /** * 演示Vector的使用.包括Vector的创 ...

随机推荐

  1. java基础系列(一):Number,Character和String类及操作

    这篇文章总结了Java中最基础的类以及常用的方法,主要有:Number,Character,String. 1.Number类 在实际开发的过程中,常常会用到需要使用对象而不是内置的数据类型的情形.所 ...

  2. 使用kubeadm部署K8S v1.17.0集群

    kubeadm部署K8S集群 安装前的准备 集群机器 172.22.34.34 K8S00 172.22.34.35 K8S01 172.22.34.36 K8S02 注意: 本文档中的 etcd . ...

  3. CenOS 7 安装Redis

    1.Redis介绍 Redis是一个使用ANSI C编写的开源.支持网络.基于内存.可选持久性的键值对存储数据库.从2015年6月开始,Redis的开发由Redis Labs赞助,而2013年5月至2 ...

  4. c#,回文数判断

    回文数:将数值反过来.如:123 反过来是321 ,如果两个数相等,则是回文,否则不是 using System; namespace ConsoleApp1 { class Program { st ...

  5. 【Linux内核】编译与配置内核(x86)

    [Linux内核]编译与配置内核(x86)  https://www.cnblogs.com/jamesharden/p/6414736.html

  6. Spring boot+Websocket实例1

    简单的demo https://github.com/callicoder/spring-boot-websocket-chat-demo

  7. 【Docker】:docker安装ELK(logstash,elasticsearch,kibana)

    一:安装logstash 1.拉取镜像 docker pull logstash:5.6.11 2.创建目录 mkdir /docker/logstash cd /docker/logstash 3. ...

  8. WUSTOJ 1246: 字符串排序(Java)

    1246: 字符串排序 题目   输入n(n<100)个字符串,每个字符串长度不超过1000,将他们按字典顺序输出.更过内容点击标题. 分析   Java中的ArrayList()可以比较方便的 ...

  9. 初始STM32

    主要内容: 1.什么是STM32 STM32有什么 STM32怎么选型号 一:什么是STM32 ST— 意法半寻体,是一个公司名,即SOC厂商(ARM是IP厂商,STM32中内核由ARM设计,外设例如 ...

  10. JS 02 函数

    函数 一.创建函数 1.function 函数名( 形参列表 ){ 函数体 } 2.var 函数名 = function( 形参列表 ) { 函数体 } 3.var 函数名 = new Functio ...