有没有办法可以使用std?
中的sort函数对矩阵元素进行排序//Using this matrix
vector<vector<string>> mat;
例如,如果你有
5 2 1
0 0 2
1 4 3
结果将是
0 0 1
1 2 2
3 4 5
答案 0 :(得分:2)
要存储矩阵,std::vector
的嵌套不是最佳解决方案。由于任何行都管理自己的大小,因此矩阵类没有内在授予的唯一列大小。
假设OP被认为使用现有类型(可能没有改变),我基于此编写了我的样本。
一个解决方案(实施工作量最少)将是
std::vector<std::vector<std::string> >
)复制到std::vector<std::string>
std::sort()
应用于此临时考虑到元素的移动可能很昂贵,可以选择
std::sort()
使用自定义较少的仿函数(考虑矩阵元素)。之后,索引对向量可用于按排序顺序访问原始矩阵元素。
后者显示在我的示例代码中:
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
typedef std::vector<std::string> Row;
typedef std::vector<Row> Matrix;
typedef std::pair<size_t, size_t> IndexPair;
struct LessMatrix {
const Matrix &mat;
LessMatrix(const Matrix &mat): mat(mat) { }
bool operator()(const IndexPair &i1, const IndexPair &i2)
{
return mat[i1.first][i1.second] < mat[i2.first][i2.second];
}
};
std::ostream& operator<<(std::ostream &out, const Matrix &mat)
{
for (const Row row : mat) {
for (const std::string elem : row) out << ' ' << elem;
out << '\n';
}
return out;
}
int main()
{
Matrix mat = {
{ "5", "2", "1" },
{ "0", "0", "2" },
{ "1", "4", "3" }
};
// print input
std::cout << "Input:\n" << mat << '\n';
// indexify matrix
std::vector<IndexPair> indices;
for (size_t i = 0, n = mat.size(); i < n; ++i) {
const std::vector<std::string> &row = mat[i];
for (size_t j = 0, m = row.size(); j < m; ++j) {
indices.push_back(std::make_pair(i, j));
}
}
// sort matrix
LessMatrix less(mat);
std::sort(indices.begin(), indices.end(), less);
// print output
Matrix matOut;
{ size_t i = 0; const size_t nCols = 3;
for (const IndexPair &index : indices) {
if (i % nCols == 0) matOut.push_back(Row());
matOut.back().push_back(mat[index.first][index.second]);
++i;
}
}
std::cout << "Output:\n" << matOut << '\n';
// done
return 0;
}
输出:
Input:
5 2 1
0 0 2
1 4 3
Output:
0 0 1
1 2 2
3 4 5
OP抱怨创建一个单独的索引向量。我怀疑自定义随机访问迭代器可能是替代(直接对矩阵排序)。我必须承认我之前没有这样做,但出于好奇,我试图解开这个问题:
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <cassert>
typedef std::vector<std::string> Row;
typedef std::vector<Row> Matrix;
struct MatrixIterator {
typedef size_t difference_type;
typedef std::string value_type;
typedef std::string* pointer;
typedef std::string& reference;
typedef std::random_access_iterator_tag iterator_category;
// accessed matrix
Matrix &mat;
// index of row, index of column
size_t i, j;
MatrixIterator(Matrix &mat, size_t i = 0, size_t j = 0): mat(mat), i(i), j(j) { }
MatrixIterator& operator =(const MatrixIterator &iter)
{
assert(&mat == &iter.mat);
i = iter.i; j = iter.j;
return *this;
}
size_t nCols() const { return mat.front().size(); }
std::string& operator *() { return mat[i][j]; }
const std::string& operator *() const { return mat[i][j]; }
MatrixIterator& operator ++() { return *this += 1; }
MatrixIterator operator ++(int) { MatrixIterator iter(*this); ++*this; return iter; }
MatrixIterator& operator --() { return *this -= 1; }
MatrixIterator operator --(int) { MatrixIterator iter(*this); --*this; return iter; }
MatrixIterator& operator += (size_t n)
{
j += i * nCols() + n; i = j / nCols(); j %= nCols(); return *this;
}
MatrixIterator operator + (size_t n) const
{
MatrixIterator iter(*this); iter += n; return iter;
}
friend MatrixIterator operator + (size_t n, const MatrixIterator &iter)
{
MatrixIterator iter2(iter); iter2 += n; return iter2;
}
MatrixIterator& operator -= (size_t n)
{
j += i * nCols() - n; i = j / nCols(); j %= nCols();
return *this;
}
MatrixIterator operator - (size_t n) const
{
MatrixIterator iter(*this); iter -= n; return iter;
}
size_t operator - (const MatrixIterator &iter) const
{
return (i * nCols() + j) - (iter.i * iter.nCols() + iter.j);
}
std::string& operator[](size_t i) { return mat[i / nCols()][i % nCols()]; }
const std::string& operator[](size_t i) const { return mat[i / nCols()][i % nCols()]; }
bool operator == (const MatrixIterator &iter) const
{
return i == iter.i && j == iter.j;
}
bool operator != (const MatrixIterator &iter) const { return !(*this == iter); }
bool operator < (const MatrixIterator &iter) const
{
return i * nCols() + j < iter.i * iter.nCols() + iter.j;
}
bool operator > (const MatrixIterator &iter) const { return iter < *this; }
bool operator <= (const MatrixIterator &iter) const { return !(iter > *this); }
bool operator >= (const MatrixIterator &iter) const { return !(*this < iter); }
};
MatrixIterator begin(Matrix &mat) { return MatrixIterator(mat, 0, 0); }
MatrixIterator end(Matrix &mat) { return MatrixIterator(mat, mat.size(), 0); }
std::ostream& operator<<(std::ostream &out, const Matrix &mat)
{
for (const Row row : mat) {
for (const std::string elem : row) out << ' ' << elem;
out << '\n';
}
return out;
}
int main()
{
Matrix mat = {
{ "5", "2", "1" },
{ "0", "0", "2" },
{ "1", "4", "3" }
};
// print input
std::cout << "Input:\n" << mat << '\n';
// sort matrix
std::sort(begin(mat), end(mat));
// print output
std::cout << "Output:\n" << mat << '\n';
// done
return 0;
}
输出:
Input:
5 2 1
0 0 2
1 4 3
Output:
0 0 1
1 2 2
3 4 5
注意:
我使用了cppreference.com上的描述
作为&#34;要求 - 作弊表&#34;并实现了那里描述的一切。一些细节,我决定猜测。 (特别是关于typedef
我不太确定如何纠正它们。)
答案 1 :(得分:1)
您可以通过创建自定义包装器矩阵类并定义自己的迭代器来对嵌套向量进行排序而无需额外的数据复制:
#include <algorithm>
#include <iterator>
#include <string>
#include <vector>
class MyMatrix {
public:
using DataStore = std::vector<std::vector<std::string> >;
// Note: Make sure MyMatrix DO NOT out-live its `data` argument!
MyMatrix(DataStore& data) : data_(data) {
// Check that
// 1. data.size() > 0;
// 2. data[i].size() > 0 and same for all valid i.
}
class Iterator : public std::iterator<std::random_access_iterator_tag,
std::string, int> {
public:
Iterator(DataStore& data) : data_(&data), index_(0) {}
Iterator(DataStore& data, int index) : data_(&data), index_(index) {}
Iterator(const Iterator& it) : data_(it.data_), index_(it.index_) {}
Iterator& operator=(const Iterator& it) {
data_ = it.data_;
index_ = it.index_;
}
operator bool() const {
return index_ >= 0 && index_ < data_->size() * (*data_)[0].size();
}
bool operator==(const Iterator& it) const {
return data_ == it.data_ && index_ == it.index_;
}
bool operator!=(const Iterator& it) const {
return data_ != it.data_ || index_ != it.index_;
}
Iterator& operator++() { ++index_; return *this; }
Iterator& operator--() { --index_; return *this; }
Iterator operator++(int) { return Iterator(*data_, index_++); }
Iterator operator--(int) { return Iterator(*data_, index_--); }
Iterator& operator+=(int offs) { index_ += offs; return *this; }
Iterator& operator-=(int offs) { index_ -= offs; return *this; }
Iterator operator+(int offs) { return Iterator(*data_, index_ + offs); }
Iterator operator-(int offs) { return Iterator(*data_, index_ - offs); }
int operator-(const Iterator& it) { return index_ - it.index_; }
std::string& operator*() {
return (*data_)[index_ / data_->size()][index_ % (*data_)[0].size()];
}
const std::string& operator*() const { return operator*(); }
private:
DataStore* data_;
int index_;
}; // class Iterator
Iterator iterator() { return Iterator(data_); }
Iterator begin() { return Iterator(data_, 0); }
Iterator end() { return Iterator(data_, data_.size() * data_[0].size()); }
private:
DataStore& data_;
}; // class MyMatrix
然后sort
可以应用于MyMatrix
,如下所示:
#include <iostream>
int main()
{
std::vector<std::vector<std::string> > store = {
{ "5", "2", "1" },
{ "0", "0", "2" },
{ "1", "4", "3" }
};
MyMatrix matrix(store);
for (const auto& row : store) {
for (const auto& item : row) { std::cout << item <<' '; }
std::cout <<'\n';
}
std::cout <<'\n';
std::sort(matrix.begin(), matrix.end());
for (const auto& row : store) {
for (const auto& item : row) { std::cout << item <<' '; }
std::cout <<'\n';
}
std::cout <<'\n';
}
运行上面的代码将产生以下输出:
5 2 1
0 0 2
1 4 3
0 0 1
1 2 2
3 4 5