2012-07-28 114 views
1

我一直在使用J.F. Sebastian的implementation两个排序数组的第k个顺序统计,并取得了一些成功。C++ reverse iterator和eigen

基本上,该算法将长度为la和lb的两个排序数组A和B作为输入,并以log(la)+ log(lb)次返回其联合的第k个最大元素。

但是,在我的应用程序中,在某些情况下,A将按降序排序。幸运的是,我事先知道这些情况是什么。所以我总是可以这样做:

A.data()A.data()+A.size()分别为A.begin()和A.end() )的特征构造。

if(normal case){    
    sol=nsmallest(A.data(),A.data()+A.size(),B.data(),B.data()+B.size(),k,std::less<float>()); 
    std::cout << sol << std::endl; 
} 

和情况下,A的递减顺序进行排序:

if(case with reverted sorted A){ 
    std::reverse(A.data(),A.data()+A.size());      
    sol=nsmallest(A.data(),A.data()+A.size(),B.data(),B.data()+B.size(),k,std::less<float>()); 
    std::cout << sol << std::endl; 
} 

这工作[:)],但看起来过于复杂[:(]和(我怀疑)效率低下,特别是因为我需要要还原到它在结束原来的顺序。

我试图通过

typedef std::vector<float>::iterator iter_int; 
上述替代

....

iter_int begin (x.segment(0,i).data());               
iter_int end (x.segment(0,i).data()+x.segment(0,i).size());            
std::reverse_iterator<iter_int> rev_end(begin);  
std::reverse_iterator<iter_int> rev_iterator(end); 

但这会导致G ++畏缩:

error: no matching function for call to ‘nsmallest(std::reverse_iterator<__gnu_cxx::__normal_iterator<float*, std::vector<float> > >&, std::reverse_iterator<__gnu_cxx::__normal_iterator<float*, std::vector<float> > >&, Eigen::PlainObjectBase<Eigen::Matrix<float, -0x00000000000000001, 1> >::Scalar*, Eigen::PlainObjectBase<Eigen::Matrix<float, -0x00000000000000001, 1> >::Scalar*, int&, std::less<float>)’ 
nosix.cpp:62:93: note: candidate is: 
nosix.cpp:19:5: note: template<class RandomIterator, class Compare> typename std::iterator_traits<_InputIterator>::value_type nsmallest(RandomIterator, RandomIterator, RandomIterator, RandomIterator, std::size_t, Compare) 

,我不知道如何解决它。

但这并没有给出预期的结果:!

#include <algorithm> 
#include <fstream> 
#include <iostream> 
#include <stdio.h> 
#include <stdlib.h> 
#include <time.h> 
#include <vector> 
#include <cassert> 
#include <iterator> 

#include <Eigen/Dense> 
using namespace Eigen; 
using Eigen::VectorXf; 
using Eigen::VectorXi; 
typedef std::vector<float>::iterator iter_int; 
template<class RandomIterator,class Compare> 
typename std::iterator_traits<RandomIterator>::value_type 
nsmallest(RandomIterator firsta,RandomIterator lasta,RandomIterator firstb,RandomIterator lastb,size_t n,Compare less) { 
    assert(n<static_cast<size_t>((lasta-firsta)+(lastb-firstb))); 
    if (firsta==lasta) return *(firstb+n); 
    if (firstb==lastb) return *(firsta+n); 

    size_t mida=(lasta-firsta)/2; 
    size_t midb=(lastb-firstb)/2; 
    if ((mida+midb)<n) 
     return less(*(firstb+midb),*(firsta+mida))? 
     nsmallest(firsta,lasta,firstb+midb+1,lastb,n-(midb+1),less): 
     nsmallest(firsta+mida+1,lasta,firstb,lastb,n-(mida+1),less); 
    else 
     return less(*(firstb+midb),*(firsta+mida))? 
     nsmallest(firsta,firsta+mida,firstb,lastb,n,less): 
     nsmallest(firsta,lasta,firstb,firstb+midb,n,less); 
} 
int main(){ 
    int p,q,n,k,l; 
    float sol; 
    std::cout << "enter p " << std::endl; 
    std::cin >> p; 
    std::cout << "enter q " << std::endl; 
    std::cin >> q; 
    n=p+q; 
    std::cout << " enter k (>=) " << std::min(p,q) << " & <= " << n-1 << std::endl; 
    std::cin >> k; 

    srand(time(NULL)); 
    VectorXf v1=VectorXf::Random(p); 
    srand(time(NULL)); 
    VectorXf v2=VectorXf::Random(q); 
    VectorXf v3(n); 
    v3 << v1, v2; //eigen-concatenation of vectors 
    std::sort(v3.data(),v3.data()+v3.size()); 
    std::sort(v1.data(),v1.data()+v1.size(),std::greater<float>()); 
    std::sort(v2.data(),v2.data()+v2.size()); 
    //this gives the intended result: 
    std::reverse(v1.data(),v1.data()+v1.size()); 
    //this doesn't :(
    /* 
    iter_int begin (v1.data()); 
    iter_int end (v1.data()+v1.size()); 
    std::reverse_iterator<iter_int> rev_end(begin); 
    std::reverse_iterator<iter_int> rev_iterator(end); 
    sol=nsmallest(rev_iterator,rev_end,v2.data(),v2.data()+v2.size(),k,std::less<float>()); 
    /**/ 
    sol=nsmallest(v1.data(),v1.data()+v1.size(),v2.data(),v2.data()+v2.size(),k,std::less<float>()); 
    //if it works, these two should return the same. 
    std::cout << sol << std::endl; 
    std::cout << v3(k) << std::endl; 
    return 0; 
} 

回答

3

您的nsmallest函数要求前4个参数的类型完全相同。

试试这个:

template<class RandomIteratorA, class RandomIteratorB, class Compare> 
typename std::iterator_traits<RandomIteratorA>::value_type 
nsmallest(RandomIteratorA firsta,RandomIteratorA lasta,RandomIteratorB firstb,RandomIteratorB lastb,size_t n,Compare less) { 
... 
} 
+0

真棒:它的工作原理上的小例子上述(i会为这些更先进的C++结构,但您的补丁固定对我来说永远无能)。 – user189035 2012-07-28 21:08:32