我有一个未排序的特征值向量和一个相关的特征向量矩阵。我想根据排序的特征值集对矩阵的列进行排序。 (例如,如果特征值[3]移动到特征值[2],我希望特征向量矩阵的第3列移到第2列。)
我知道我可以通过O(N log N)
对std::sort
中的特征值进行排序。如果不滚动我自己的排序算法,我如何确保矩阵的列(相关的特征向量)跟随它们的特征值,因为后者是排序的?
答案 0 :(得分:7)
通常只需创建一个类似这样的结构:
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
。< / p>
答案 1 :(得分:2)
我在不同的情况下做了很多次。而不是对数组进行排序,只需创建一个新的数组,其中包含已排序的索引。
例如,你有一个长度为n的数组(向量)evals,并且有一个2d nxn数组。创建一个包含值[0,n-1]的新数组索引。
然后,不是将evals作为evals [i]访问,而是将其作为evals [index [i]]访问,而不是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数组关联的任何内容进行排序,而无需实际移动内存。当n变大时,这很重要,您不希望在evects矩阵的列周围移动。
基本上,我最小的eval将位于index [i],并且对应于索引[i] thve。
编辑添加。这是一个排序函数,我已经编写过使用std :: 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];
}
};
答案 2 :(得分:0)
解决方案纯粹依赖于存储特征向量矩阵的方式。
如果您可以实现swap(evector1, evector2)
以便它只重新绑定指针并且实际数据保持不变,那么排序时的最佳性能将会实现。
这可以使用像double*
这样的东西来完成,或者可能更复杂一些,取决于你的矩阵实现。
如果这样做,swap(...)
不会影响您的排序操作性能。
答案 3 :(得分:0)
将矢量和矩阵联合起来的想法可能是在C ++中实现它的最佳方法。我正在考虑如何在R中执行此操作并查看是否可以将其转换为C ++。在R中它非常简单,只需要evec&lt; -evec [,order(eval)]。不幸的是,我不知道在C ++中执行order()操作的任何内置方法。也许其他人也这样做,在这种情况下,这可以用类似的方式完成。