码迷,mamicode.com
首页 > 编程语言 > 详细

C++ 中对vector<T*> 数组的查找和排序

时间:2015-06-05 22:33:14      阅读:270      评论:0      收藏:0      [点我收藏+]

标签:



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

#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 = 1;

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(2));
    arry.push_back(new CA(21));
    arry.push_back(new CA(3));
    arry.push_back(new CA(1));
    arry.push_back(new CA(4));
    arry.push_back(new CA(1));
    arry.push_back(new CA(12));
}
//---------------------------------------------------------------------------


void __fastcall TForm1::Button1Click(TObject *Sender)
{
    sort(arry.begin(),arry.end(),Compare);
    for(unsigned i = 0; i < arry.size(); i++)
    {
        ShowMessage(IntToStr(arry[i]->a));
    }

    vector<CA*>::iterator itor = find(arry.begin(),arry.end(),21);
    if (itor != arry.end())
    {
        ShowMessage("find!");
    }


    vector<CA*> range = FindRange<CA,int>(arry.begin(),arry.end(),1);
    ShowMessage("find "+IntToStr(range.size())+" number");

    globA = 1;
    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 =0; 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) >> 2;

  for ( ; __trip_count > 0 ; --__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 3:
    if (*__first == __val) return __first;
    ++__first;
  case 2:
    if (*__first == __val) return __first;
    ++__first;
  case 1:
    if (*__first == __val) return __first;
    ++__first;
  case 0:
  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) >> 2;

  for ( ; __trip_count > 0 ; --__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 3:
    if (__pred(*__first)) return __first;
    ++__first;
  case 2:
    if (__pred(*__first)) return __first;
    ++__first;
  case 1:
    if (__pred(*__first)) return __first;
    //    ++__first;  我不知道为什么这里有这样的注释,C++ BUILDER 6 里面的代码就是这样的。可见,标准库也是人写的。
  case 0:
  default:
    return __last;
  }
}

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

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

/***
 * 使用find_if
 */
static int globA = 1;

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*> 数组的查找和排序

标签:

原文地址:http://www.cnblogs.com/songr/p/4555677.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!