我有一个未排序的特征向量和特征向量矩阵。我想对排序的特征值集合对矩阵的列进行排序。 (例如,如果特征值[3]移动到特征值[2],我想特征向量矩阵的列3移动到列2.)按特征值排序特征向量(相关排序)
我知道我可以通过std::sort
排序O(N log N)
的特征值。如果没有滚动我自己的排序算法,我如何确定矩阵的列(相关的特征向量)以及它们的特征值,因为后者是排序的?
我有一个未排序的特征向量和特征向量矩阵。我想对排序的特征值集合对矩阵的列进行排序。 (例如,如果特征值[3]移动到特征值[2],我想特征向量矩阵的列3移动到列2.)按特征值排序特征向量(相关排序)
我知道我可以通过std::sort
排序O(N log N)
的特征值。如果没有滚动我自己的排序算法,我如何确定矩阵的列(相关的特征向量)以及它们的特征值,因为后者是排序的?
通常只需要创建一个结构是这样的:
struct eigen {
int value;
double *vector;
bool operator<(eigen const &other) const {
return value < other.value;
}
};
或者,只是把特征值/特征向量为std::pair
- 尽管我宁愿eigen.value
和eigen.vector
在something.first
和something.second
。
该解决方案完全依赖于存储您的特征向量矩阵的方式。
如果您可以实现swap(evector1, evector2)
,则可以实现排序时的最佳性能,以便仅重新绑定指针并保持实际数据不变。
这可以使用类似double*
或可能更复杂的东西来完成,取决于您的矩阵实现。
如果以这种方式完成,swap(...)
不会影响您的分类操作性能。
聚合你的向量和矩阵的想法可能是在C++中完成它的最好方法。我正在考虑如何在R中做这件事,看看它是否可以转换为C++。在R中,它非常简单,只需简单地将evec < -evec [,order(eval)]。不幸的是,我不知道在C++中执行order()操作的内置方式。也许别人会这样做,在这种情况下,这可以用类似的方式完成。
我在不同的情况下做了很多次。而不是排序数组,只需创建一个新的数组,其中有排序的索引。
例如,您有一个长度为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];
}
};
有趣;感谢你的回答。 – fbrereto 2010-04-21 22:46:09
+1指出std :: pair技巧。 – ypnos 2010-04-21 21:24:11
@Jerry:这是一个可靠的解决方案。我唯一的想法是看看我是否可以做相关的排序,而不必在向量/矩阵和排序结构(对)之间来回复制数据,因为我需要以矩阵形式排序的特征向量。不过,我要从这开始,谢谢。 – fbrereto 2010-04-21 21:31:18
@fbrereto:你可能更喜欢这样排序,然后(如果你必须)重新排列数据到最终订单。在排序过程中交换完整的特征向量可能会比提取这些特征向量更慢,排序,然后将特征向量重新排列为最终顺序。 – 2010-04-21 21:43:25