簡體   English   中英

按方案對矩陣進行排序

[英]Sort matrix by scheme

我需要按下面的方案對矩陣的負元素進行排序。 我試圖從另一個角落進行排序,但它也不起作用。 我認為,我需要將矩陣元素放在一維數組中。 它應該在雞尾酒排序中排序,但排序的類型不是我的主要問題。

方案

我的代碼:

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++;
        }
    }
}
}

這個問題聽起來很簡單,但事實並非如此。 其中有很多“間接”,您需要使用索引而不是值。

我很快檢查了你的代碼。 它主要是 C 代碼(不是 C++)和錯誤的。

例子:

int t;
rt = t;

有了它,您就有了一個未初始化的變量,用作數組索引。 這是一個致命的錯誤。 您還使用了 VLA(可變長度數組)。 這在 C++ 中是不允許的。 而且您使用的是普通的 C 樣式數組。 這是你不應該做的。 使用std::vector ,它可以動態增長或至少使用std::array代替。 並且請給你的變量更有意義的名字。

我將向您展示一個(在眾多可能的解決方案中),但我將使用 C++。

手頭問題的核心是找到給定矩陣中元素的行和列索引。 這並不容易。

但是好吧,讓我們從那個開始。 如果您使用矩陣繪制圖片,然后在對角線上添加虛線,您就會看到索引。

在此處輸入圖片說明

如果矩陣的維度是dim那么總是有dim + dim – 1對角線。 對角線首先具有增加的元素數量,在碰到中間最長的主要對角線后,元素數量減少。 所以我們迭代所有對角線的數量,由中間對角線分割,並計算相應的行和列索引。 這有點棘手,但過一段時間你就會發現。

生成的行和列索引將存儲在結構中。 具有所有行和列索引的所有對角線將存儲在結構向量中。 此外,我們添加原始矩陣單元格的值。

關於排序。 開發自己的排序算法顯然是您的任務。 為此,我創建了一個函數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;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM