2010-04-21 168 views
4

我有一个未排序的特征向量和特征向量矩阵。我想对排序的特征值集合对矩阵的列进行排序。 (例如,如果特征值[3]移动到特征值[2],我想特征向量矩阵的列3移动到列2.)按特征值排序特征向量(相关排序)

我知道我可以通过std::sort排序O(N log N)的特征值。如果没有滚动我自己的排序算法,我如何确定矩阵的列(相关的特征向量)以及它们的特征值,因为后者是排序的?

回答

7

通常只需要创建一个结构是这样的:

struct eigen { 
    int value; 
    double *vector; 

    bool operator<(eigen const &other) const { 
     return value < other.value; 
    } 
}; 

或者,只是把特征值/特征向量为std::pair - 尽管我宁愿eigen.valueeigen.vectorsomething.firstsomething.second

+0

+1指出std :: pair技巧。 – ypnos 2010-04-21 21:24:11

+0

@Jerry:这是一个可靠的解决方案。我唯一的想法是看看我是否可以做相关的排序,而不必在向量/矩阵和排序结构(对)之间来回复制数据,因为我需要以矩阵形式排序的特征向量。不过,我要从这开始,谢谢。 – fbrereto 2010-04-21 21:31:18

+0

@fbrereto:你可能更喜欢这样排序,然后(如果你必须)重新排列数据到最终订单。在排序过程中交换完整的特征向量可能会比提取这些特征向量更慢,排序,然后将特征向量重新排列为最终顺序。 – 2010-04-21 21:43:25

0

该解决方案完全依赖于存储您的特征向量矩阵的方式。

如果您可以实现swap(evector1, evector2),则可以实现排序时的最佳性能,以便仅重新绑定指针并保持实际数据不变。

这可以使用类似double*或可能更复杂的东西来完成,取决于您的矩阵实现。

如果以这种方式完成,swap(...)不会影响您的分类操作性能。

0

聚合你的向量和矩阵的想法可能是在C++中完成它的最好方法。我正在考虑如何在R中做这件事,看看它是否可以转换为C++。在R中,它非常简单,只需简单地将evec < -evec [,order(eval)]。不幸的是,我不知道在C++中执行order()操作的内置方式。也许别人会这样做,在这种情况下,这可以用类似的方式完成。

2

我在不同的情况下做了很多次。而不是排序数组,只需创建一个新的数组,其中有排序的索引。

例如,您有一个长度为n的数组(矢量)evals,并且一个2d nxn数组会相隔。创建一个包含值[0,n-1]的新数组索引。

然后,您不是通过访问evals [i],而是将它作为evals [index]访问,而不是evects [i] [j],您可以访问它evects [index [i]] [j] 。

现在,您编写排序例程来对索引数组进行排序,而不是对evals数组进行排序,因此索引数组中的值不会像索引{0,1,2,...,n-1}按evals数组中的值的升序排列。

所以排序之后,如果你这样做:

for (int i=0;i<n;++i) 
{ 
    cout << evals[index[i]] << endl; 
} 

你会得到evals的排序列表。

通过这种方式,您可以排序与evals数组关联的任何内容,而无需实际移动内存。当n变大时,这是很重要的,你不想在矩阵的矩阵列上移动。

基本上,第i个最小的eval将位于索引[i]处并且对应于索引[i] thve。

编辑添加。这里有一个我用std :: sort编写的sort函数来完成我刚才所说的:

template <class DataType, class IndexType> 
class SortIndicesInc 
{ 
protected: 
    DataType* mData; 
public: 
    SortIndicesInc(DataType* Data) : mData(Data) {} 
    Bool operator()(const IndexType& i, const IndexType& j) const 
    { 
     return mData[i]<mData[j]; 
    } 
}; 
+0

有趣;感谢你的回答。 – fbrereto 2010-04-21 22:46:09