C++ 反向迭代器和 Eigen

标签 c++ eigen

我一直在使用 J.F. Sebastian 的 implementation两个排序数组的第 k 阶统计量的一些成功。

基本上,该算法将长度为 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;
}

这有效 [ :) ] 但看起来过于复杂 [ :( ] 并且(我怀疑)效率低下,特别是因为我需要在最后将 A 恢复到它的原始顺序。

我尝试用

替换上面的 std::reverse
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;  
} 

最佳答案

您的 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) {
...
}

关于C++ 反向迭代器和 Eigen ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11704321/

相关文章:

c++ - 具有中间变量的 Eigen 惰性评估

c++ - 具有特征类的不合格 ID

c++ - 使用front()方法使队列数据结构应用崩溃

c++11线程类如何使用类成员函数

c++ - 如何从 C++ 中的集合中删除一个项目而不删除它?

linear-algebra - 什么时候使用 eigen 什么时候使用 Blas

c++ - Armadillo 的solve(A, b)从Matlab、Eigen返回不同的答案

c++ - 在 eigen 中使用 std::nth_element 和相关的询问

c++ - 任何查看 C/CPP 应用程序内存数据结构的方法?

C++ 对象不适用于点运算符