我需要按以下方案对矩阵的负元素进行排序。我试图从另一个角度进行排序,但是它也不起作用。我认为,我需要将矩阵元素放入一维数组中。应该按鸡尾酒排序,但是排序的类型不是我的主要问题。
我的代码:
int main() {
const int n = 4, m = 4;
int t, v[n*m], arr[n][m], i, j, tmp, lt, rt;
lt = 0;
rt = t;
srand(time(NULL));
for (i = 0; i < n; i++) {
for(j=0; j < m; j++) {
arr[i][j] = rand() % 100 - 50;
}
cout << endl;
}
t = 0;
for (i = 0; i < n; i++) {
for(j = 0; j < m; j++) {
if (arr[i][j] < 0) {
v[t] = arr[i][j];
t++;
}
}
}
while(lt <= rt) {
for (i = rt; i >= lt; i--) {
if(v[i] > v[i-1]) {
swap(v[i], v[i-1]);
}
}
lt++;
for (i = lt; i <=rt; i++) {
if(v[i] > v[i-1]) {
swap(v[i], v[i-1]);
}
}
rt--;
}
for (i = 0; i < t; i++) {
cout << v[i] << " ";
}
int r = 0;
for (i = 0; i < n; i++) {
for(j = 0; j < m; j++) {
if(arr[i][j] < 0) {
arr[i][j] = v[r];
r++;
}
}
}
}
答案 0 :(得分:1)
这个问题听起来很简单,但事实并非如此。其中有很多“间接”,您需要在其中使用索引而不是值。
我很快检查了您的代码。主要是C代码(不是C ++)和越野车。
示例:
int t;
rt = t;
具有一个未初始化的变量,用作数组索引。那是一个致命的错误。您还使用了VLA(可变长度数组)。这在C ++中是不允许的。您正在使用纯C样式数组。您不应该这样做。使用std::vector
,它可以动态增长,也可以至少增长std::array
。并请给您的变量更有意义的名称。
我将向您展示(一种可能的)解决方案,但是我将使用C ++。
当前问题的核心是找到给定矩阵中元素的行和列索引。那不容易。
但是好的,让我们开始吧。如果您使用矩阵绘制图片,然后在对角线上添加虚线,则会看到索引。
如果矩阵的维数为dim
,则总是有dim + dim – 1
个对角线。对角线首先具有增加的元素数,然后在中间的主要最长的对角线上命中,元素数量减少。因此,我们遍历所有对角线的数量,除以中间对角线,然后计算相应的行和列索引。这有点棘手,但是一段时间后您会发现。
结果行和列索引将存储在结构中。具有所有行和列索引的所有对角线将存储在struct向量中。此外,我们将原始矩阵单元的值相加。
关于排序。开发自己的排序算法显然是您的任务。为此,我创建了一个函数yourSort
,您可以在其中放入自己的算法。我只是使用标准算法(std::sort
)。您可以用自己的函数替换std::sort
。
主要,我放置了一些驱动程序代码。首先,我们创建一个矩阵,并用随机值填充它。然后我们计算行索引和列索引。具有负值的条目将被提取并排序。然后,将结果复制回原始矩阵。
如上所述,由于索引的间接性和仅使用负数的约束,所以不太容易。
但是无论如何。请参阅:
#include <iostream>
#include <vector>
#include <utility>
#include <random>
#include <algorithm>
#include <iterator>
#include <iomanip>
// Create types that are easy to understand
using RowIndex = size_t;
using ColumnIndex = size_t;
// Here we store the position (row and column) and the value of one cell in the matrix
struct PositionAndValue {
// Constructors
PositionAndValue() {};
PositionAndValue(const RowIndex r, const ColumnIndex c, const int v) : rowIndex(r), columnIndex(c), value(v) {};
// Data
RowIndex rowIndex{};
ColumnIndex columnIndex{};
int value{};
};
// Main data types
using Columns = std::vector<int>;
using Matrix = std::vector<Columns>;
using Diagonal = std::vector<PositionAndValue>;
// Fill matrix with random values. Standard function
void fillMatrixRandom(Matrix& m) {
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<> dis(-50, 50);
std::for_each(m.begin(), m.end(), [&](Columns &c) {std::for_each(c.begin(), c.end(), [&](int &j) { j = dis(gen);}); });
}
// Calculate the indices for all diagonals
Diagonal calculateDiagonalIndices(const Matrix& matrix) {
// The return value
Diagonal diagonalIndices{};
// Matrix dimension
const size_t MatrixDimension{ matrix.size() };
// Overall number of diagonals for this matrix
const size_t NumberOfDiagonals{ MatrixDimension + MatrixDimension - 1 };
// index of middle (longest) diagonal
const size_t MiddleDiagonal { NumberOfDiagonals / 2 + 1 };
// Counter for element index in one specific diagonal
size_t elementInDiagonal{ 0 };
for (size_t diagonalIndex = 1; diagonalIndex <= NumberOfDiagonals; ++diagonalIndex) {
// If we are above the middle diagonal
if (diagonalIndex <= MiddleDiagonal) {
// Number of elements in diagonal will increase
++elementInDiagonal;
for (size_t j = 0; j < elementInDiagonal; ++j) {
// Calculate row and column and add to result
const RowIndex row{ j };
const ColumnIndex col{ diagonalIndex - j - 1 };
diagonalIndices.emplace_back(PositionAndValue(row, col, matrix[row][col]));
}
}
else {
// We are below the middle diagonal
// Number of elements in diagonal will decrease
--elementInDiagonal;
for (size_t j = 0; j < elementInDiagonal; ++j) {
// Calculate row and column and add to result
const RowIndex row{ diagonalIndex + j - MatrixDimension };
const ColumnIndex col{ MatrixDimension - j - 1 };
diagonalIndices.emplace_back(PositionAndValue(row, col, matrix[row][col]));
}
}
}
return diagonalIndices;
}
// Simple sorting function using std algorithms
template <typename T, typename ValueType>
void yourSort(std::vector<T>& vec, ValueType T::* mPtr) {
// We will extract the negative values
std::vector<ValueType> vt{};
// Extract
std::transform(vec.begin(), vec.end(), std::back_inserter(vt), [&](const T & s) {return s.*mPtr; });
// Sort. ***** Please put here your sorting function
std::sort(vt.begin(), vt.end());
// Put back
std::for_each(vec.begin(), vec.end(), [&, i = 0U](T& s) mutable{s.*mPtr = vt[i++]; });
}
// Driver code
int main() {
// Lets use a matrix of this size
constexpr size_t MatrixDimension = 4U;
// Small lambda for printing a matrix
auto printMatrix = [](const Matrix & m) {std::for_each(m.begin(), m.end(), [](const Columns & c) {
for (int i : c) std::cout << std::setw(4) << i; std::cout << "\n"; }); std::cout << "\n"; };
// Define a matrix and fill it with random values
Matrix matrix(MatrixDimension, Columns(MatrixDimension));
fillMatrixRandom(matrix);
printMatrix(matrix);
// Calulate the indices on the diagonals
Diagonal diagonal{ calculateDiagonalIndices(matrix) };
// Extract the negatives
Diagonal negativesOnDiagonal{};
std::copy_if(diagonal.begin(), diagonal.end(), std::back_inserter(negativesOnDiagonal),
[](const PositionAndValue & pv) { return pv.value < 0; });
// Sort
yourSort(negativesOnDiagonal, &PositionAndValue::value);
// Copy back
std::for_each(negativesOnDiagonal.begin(), negativesOnDiagonal.end(),
[&matrix](const PositionAndValue & pv) { matrix[pv.rowIndex][pv.columnIndex] = pv.value; });
printMatrix(matrix);
return 0;
}