在二维数组 C++ 中交换行

Swapping rows in 2-D array C++

是的,我写了一个程序,根据每一行中所有正偶数元素的总和,对二维数组的行进行升序排序,但它不能正常工作。有时它可以正确地交换行,但大多数时候感觉这个程序只交换两个相邻的行或类似的东西。

很可能,对二维数组使用冒泡排序不正确存在问题。这是我做最多事情的函数:

void print(int** arr, int rows, int columns) {
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < columns; j++) {
            cout << setw(7) << arr[i][j];
        }
        cout << endl;
    }
    int* sumRows = new int[rows];
    int sum = 0;
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < columns; j++) {
            if (arr[i][j] > 0 && arr[i][j] % 2 == 0)
            {
                //cout << setw(7) << arr[i][j];
                sum = sum + arr[i][j];
            }
        }
        cout << endl << "Sum of positive even elements in the row " << i + 1 << " = " << sum;
        sumRows[i] = sum;
        sum = 0;
    }
    cout << endl << "Array of sums: ";
    for (int i = 0; i < rows; i++) {
        cout << setw(7) << sumRows[i];
    }

    //for (int i = 0; i < r; i++) cout << setw(7) << sumRows[i];
    cout << endl;

    bool swapped;
    for (int i = 0; i < rows - 1; i++)
    {
        swapped = false;
        for (int j = 0; j < columns - 1; j++)
        {
            for (int k = 0; k < rows - i - 1; k++) {
                if (sumRows[k] > sumRows[k + 1])
                {
                    swap(arr[k][j], arr[k + 1][j]);
                    swapped = true;
                }
            }
        }

        if (swapped == false) break;
    }

    cout << endl << endl << "Swapped array:" << endl;
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < columns; j++) {
            cout << setw(7) << arr[i][j];
        }
        cout << endl;
    }
}

完整代码:

#include <iostream>
#include <iomanip>
#include <time.h>
#include <conio.h>
#include <algorithm>
using namespace std;

int** createMalloc(int, int);
int** createCalloc(int rows, int columns);

int** createNew(int rows, int columns);
void deleteNew(int** arr, int rows);

void init(int**, int, int);
void freeMemory(int**, int);
void print(int**, const int, const int);

void initPrint(int** arr, int rows, int columns);

void main() {
    int rowCount, colCount;
    cout << "Enter number of rows: "; cin >> rowCount;
    cout << "Enter number of columns: "; cin >> colCount;
    cout << " Array creation algorithm\n";
start:
    cout << "Input number : \n1 for malloc\n2 for calloc\n3 for new\n";
    int k;
    cin >> k;
    switch (k) {
    case 1: {
        int** a = createMalloc(rowCount, colCount);
        initPrint(a, rowCount, colCount);

        freeMemory(a, rowCount);
        break;
    }
    case 2: {
        int** a = createCalloc(rowCount, colCount);
        initPrint(a, rowCount, colCount);

        freeMemory(a, rowCount);
        break;
    }
    case 3: {
        int** a = createNew(rowCount, colCount);
        initPrint(a, rowCount, colCount);

        deleteNew(a, rowCount);
        break;
    }
    default:cout << "Input 1, 2 or 3, please.";
        cout << endl << endl;
        goto start;
    }
    cout << endl << endl;
}

int** createMalloc(int rows, int columns) {
    int** arr = (int**)malloc(rows * sizeof(int*));
    for (int i = 0; i < rows; i++) {
        arr[i] = (int*)malloc(columns * sizeof(int));
    }
    return arr;
}

int** createCalloc(int rows, int columns) {
    int** arr = (int**)calloc(rows, sizeof(int*));
    for (int i = 0; i < rows; i++) {
        arr[i] = (int*)calloc(columns, sizeof(int));
    }
    return arr;
}

int** createNew(int rows, int columns) {
    int** arr = new int* [rows];
    for (int i = 0; i < rows; i++) {
        arr[i] = new int[columns];
    }
    return arr;
}

void initPrint(int** arr, int rows, int columns) {
    init(arr, rows, columns);
    print(arr, rows, columns);
}

void init(int** arr, int rows, int columns) {
    const int Low = -10, High = 10;
    srand((unsigned)time(NULL));
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < columns; j++) {
            arr[i][j] = Low + rand() % (High - Low + 1);
        }
    }
}

void freeMemory(int** arr, int rows) {
    for (int i = 0; i < rows; i++) {
        free(arr[i]);
    }
    free(arr);
}

void deleteNew(int** arr, int rows) {
    for (int i = 0; i < rows; i++) {
        delete[] arr[i];
    }
    delete[] arr;
}

void print(int** arr, int rows, int columns) {
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < columns; j++) {
            cout << setw(7) << arr[i][j];
        }
        cout << endl;
    }
    int* sumRows = new int[rows];
    int sum = 0;
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < columns; j++) {
            if (arr[i][j] > 0 && arr[i][j] % 2 == 0)
            {
                //cout << setw(7) << arr[i][j];
                sum = sum + arr[i][j];
            }
        }
        cout << endl << "Sum of positive even elements in the row " << i + 1 << " = " << sum;
        sumRows[i] = sum;
        sum = 0;
    }
    cout << endl << "Array of sums: ";
    for (int i = 0; i < rows; i++) {
        cout << setw(7) << sumRows[i];
    }

    //for (int i = 0; i < r; i++) cout << setw(7) << sumRows[i];
    cout << endl;

    bool swapped;
    for (int i = 0; i < rows - 1; i++)
    {
        swapped = false;
        for (int j = 0; j < columns - 1; j++)
        {
            for (int k = 0; k < rows - i - 1; k++) {
                if (sumRows[k] > sumRows[k + 1])
                {
                    swap(arr[k][j], arr[k + 1][j]);
                    swapped = true;
                }
            }
        }

        //IF no two elements were swapped by inner loop, then break 
        if (swapped == false) break;
    }

    cout << endl << endl << "Swapped array:" << endl;
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < columns; j++) {
            cout << setw(7) << arr[i][j];
        }
        cout << endl;
    }
}

P.S。二维数组必须是动态的。此外,我需要让用户选择使用 malloccallocnew 创建数组。此外,还不能使用 vector 完成此任务。

P.P.S。我知道你们中的大多数人会觉得这很容易,但对我来说绝对不是,因为这个任务是我在大学的作业,我们没有学习任何排序算法。无论如何,当我问老师如何对行进行排序时,他告诉我使用冒泡排序所以我在这里

这 3 个循环让我很担心,所以我去 wikipedia 检查我的假设。

完全未经测试的代码,使用风险自负

void BSort(int **arr, int *sumRows, int rows, int columns) {
    bool swapped;
    while (true) {
        swapped = false;
        for (int k = 0; k < rows - 1; k++, rows--) { // reduce max row
            if (sumRows[k] > sumRows[k + 1]) {
                swap(arr[k], arr[k + 1]); // swaps the pointers
                swap(sumRows[k], sumRows[k + 1]); // swap the sums too or we swap on false conditions afterward.
                swapped = true;
            }
        }

        if (swapped == false) break;
    }
}

进一步

  • 你应该以某种方式交换你的 goto 循环。
  • sumRows 未被删除。
  • 使用较小的代码块,使用 sumRows、冒泡排序等函数

基本上你的程序已经不错了。 (排序问题除外)

但是,我想向您展示一个使用面向对象方法的更“C++ 风格”的解决方案。

这是一个完整且经过测试的代码,带有大量注释,以便于理解。

我们将所有数据封装在 class 中,并添加操作该数据的方法。我们这样做是因为外界不应该对我们的内部数据表示感兴趣。我们可以更改 class 内部结构,世界其他地方的任何人都不会注意到它。

此外,class的所有函数都可以访问class的数据。所以,我们不会用不必要的数据污染命名空间。

分配方法的实施只是一个练习,并没有增加太多价值。这只是打字工作。

为了简化输出,我们覆盖了 class' 插入器运算符。这一点都不复杂,让我们可以直观地使用现有的 ostream,比如 std::cout.

排序函数有问题。您只想按给定谓词对行进行排序:行列中偶数正数的总和。

请注意:无需触摸任何列数据。如果需要交换,我们只需交换指向所需行的指针。因此,列值不多,只有一个指向第一列值的行指针。这样效率很高。

请注意。在此示例中,您无法预先计算行的总和,因为需要交换行。

如果我们想这样做,我们需要引入一个数据结构,由列值和总和组成。也很容易成为可能。或者,如果有额外的预先计算的行总和数组,我们也需要交换这些值。但是在下面的解决方案中,我们采用了简单的方法,每次都重新计算行值,并为此浪费了很多时间。 . .

无论如何。请检查以下示例:

#include <iostream>
#include <cstdlib>
#include <ctime>
#include <algorithm>

// Lower and Upper Bound of our random test values
constexpr int LowerBound = -10;
constexpr int UpperBound = 10;

// We may have 3 different types of allocators
enum class Allocater { New, Malloc, Calloc};

// An ultra simple, stripped down representation of a 2d array with 3 types of allocaters
class Array2D {
    const Allocater allocater{};                    // Type of allocator. Default is new
    const size_t numberOfRows{};                    // Number of Rows in the 2d array
    const size_t numberOfColumns{};                 // Number of Columns of our 2d array
    int** data{};

    void allocaterMalloc();                         // Allocation using malloc
    void allocaterCalloc();                         // Allocation using calloc
    void allocaterNew();                            // Allocation using new
    void deallocateMallocCalloc();                  // Deallocatio using calloc and malloc
    void deallocateNew();                           // Deallocation using new 
    void initData();                                // Initialize our 2d array with random data
    int sumOfPositiveEvenValuesIn(size_t row) const;// Predicate function to calculate row sums for even positive values 

public:
    // Constructor. Buidl an array with given number of rows and columns using a given allocator implementation
    explicit Array2D(const size_t numRows, const size_t numColumns, Allocater alloc = Allocater::New);
    Array2D() = delete;                             // No default constructor
    ~Array2D();                                     // Free all allocated memory

    friend std::ostream& operator << (std::ostream& os, const Array2D& a2d); // Simple output
    void sort();                                    // Sort according to predicate
};

// ---------------------------------------------------------------------------------------------------------
// Main constructor. Build a 2d array with given number of rows and columns using the given allocator method
Array2D::Array2D(const size_t numRows, const size_t numColumns, Allocater alloc) : allocater(alloc), numberOfRows(numRows), numberOfColumns(numColumns) {
    // Depending on the requested method, allocate the memory for our 2d array
    switch (allocater) {
    case Allocater::Malloc:                         // We shall us malloc
        allocaterMalloc();                          // Call apropriate allocater
        break;
    case Allocater::Calloc:                         // We shall use calloc
        allocaterCalloc();                          // Call apropriate allocater
        break;
    case Allocater::New: // Fallthrough             // We shal use new
    default:                                        // Or, if there is some unknown specifier (should never happen)
        allocaterNew();                             // Call apropriate allocater
        break;
    }
    if (data) initData();                           // And initialize our 2d array with random values
}

// Destructor: Release all allocated memory 
Array2D::~Array2D() {
    // Call appropriate deallocator
    if (allocater == Allocater::Malloc || allocater == Allocater::Calloc)
        deallocateMallocCalloc();                   // Deallocate using std::free
    else
        deallocateNew();                            // Deallocate using delete
}

// --------------------------------
// The different alloctor functions

void Array2D::allocaterMalloc() {

    // First get memory to store the row pointer that will later point to the first coulmn of the row
    data = static_cast<int**>(std::malloc(numberOfRows * sizeof(int*)));

    // Now get space for all coulmns in this row
    if (data) for (size_t row{}; row < numberOfRows; ++row)
        data[row] = static_cast<int*>(std::malloc(numberOfColumns * sizeof(int)));
}

void Array2D::allocaterCalloc() {
    // First get memory to store the row pointer that will later point to the first coulmn of the row
    data = static_cast<int**>(std::calloc(numberOfRows, sizeof(int*)));

    // Now get space for all coulmns in this row
    if (data)for (size_t row{}; row < numberOfRows; ++row)
        data[row] = static_cast<int*>(std::calloc(numberOfColumns, sizeof(int)));
}
void Array2D::allocaterNew() {
    // First get memory to store the row pointer that will later point to the first coulmn of the row
    data = new int* [numberOfRows];

    // Now get space for all coulmns in this row
    if (data) for (size_t row{}; row < numberOfRows; ++row)
        data[row] = new int[numberOfColumns];
}

// --------------------
// And the deallocators
void Array2D::deallocateMallocCalloc() {
    if (data) for (size_t row{}; row < numberOfRows; ++row)
        std::free(data[row]);                   // Free each row with columns
    std::free(data);                            // Free all rows
}
void Array2D::deallocateNew() {
    if (data) for (size_t row{}; row < numberOfRows; ++row)
        delete[] data[row];                     // Free each row with columns
    delete[] data;                              // Free all rows
}
//-------------------------------------------
// Initialize our 2d array with random values
void Array2D::initData() {
    // Seed the random generator
    std::srand(static_cast<unsigned int>(std::time(NULL)));

    // Calculate a random value for all data in our 2d array
    if (data) for (size_t row{}; row < numberOfRows; ++row)                     // For all rows
            if (data[row])  for (size_t col{}; col < numberOfColumns; ++col)    // For all columns
                data[row][col] = LowerBound + (std::rand() % (UpperBound - LowerBound + 1));
}
//--------------------------------------------------------------
// A function which calculates the positive even values of a row
int Array2D::sumOfPositiveEvenValuesIn(size_t row) const {
    int sum{};
    // Iterate over values in a given row
    for (size_t col{}; col < numberOfColumns; ++col)
        // Predicate
        if (data[row] && (data[row][col] > 0) && ((data[row][col] % 2) == 0))
            sum += data[row][col];              // Calculate the sum
    return sum;                                 // Return result
}
//-------------------------------------------------------------------
// Simple output function. Overwrite inserter operator for this class
std::ostream& operator << (std::ostream& os, const Array2D& a2d) {

    // For all rows
    if (a2d.data) for (size_t row{}; row < a2d.numberOfRows; ++row) {

        // For all columns
        if (a2d.data[row]) for (size_t col{}; col < a2d.numberOfColumns; ++col)
            os << a2d.data[row][col] << '\t';                       // Show column values
        os << '\t' << a2d.sumOfPositiveEvenValuesIn(row) << '\n';   // Show conditional sum of columns
    }
    return os << "\n\n";
}
//--------------------------------------
// Bubble sort. Algorithm from Wikipedia
void Array2D::sort() {
    bool swapped{};             // Optimization. If there is now more swap, we can stop
    size_t n{ numberOfRows };   // NUmber of rows in our 2d array
    do {
        swapped = false;        // In the beginning, we did not do any swapping
        for (size_t row{}; row < (n - 1); ++row)

            // We must call the function everytime, because the rows are swapped
            if (sumOfPositiveEvenValuesIn(row) > sumOfPositiveEvenValuesIn(row + 1)) {

                // Swap pointer only. Do not touchg column values at all
                std::swap(data[row], data[row + 1]);
                swapped = true;
            }
        --n;
    } while (swapped);
}

int main() {

    // Define iportant variables
    size_t rowCount{}, columnCount{}, allocaterSelection{};
    Allocater allocater{};
    // Shwo main menu
    std::cout << "\n\nYou need to specify 3 values:\n"
        "1. Enter the allocater method\n"
        "   Enter 1 for malloc      or\n"
        "   Enter 2 for calloc      or\n"
        "   Enter any other number for new\n"
        "2. Then enter the number of rows\n"
        "3. Then enter the number of columns.\n\n";

    // Get user selection and check, if that worked
    if (std::cin >> allocaterSelection >> rowCount >> columnCount) {
        // Depending on user selection for the allocation algorithm
        switch (allocaterSelection) {
        case 1:
            allocater = Allocater::Malloc;
            break;
        case 2:
            allocater = Allocater::Calloc;
            break;
        default: // fallthrough
        case 3:
            allocater = Allocater::New;
            break;
        }

        // Now define our array and initialize all data
        Array2D array2d(rowCount, columnCount, allocater);

        // Show data to user
        std::cout << "\n\n\nData:\n\n" << array2d;

        // Sort
        array2d.sort();

        // Show sorted data to user
        std::cout << "Sorted\n\n" << array2d;
    }
    return 0;
}

如有问题请追问

真正帮助我的是:

void swapInitial(int** arr, int* sumRows, int rows, int columns) {
    bool swapped;
    for (int i = 0; i < rows - 1; i++)
    {
        swapped = false;

        for (int k = 0; k < rows - i - 1; k++) {
            if (sumRows[k] > sumRows[k + 1])
            {
                swap(arr[k], arr[k + 1]); 
                swap(sumRows[k], sumRows[k + 1]); 
                swapped = true;
            }
        }

        if (swapped == false) break;
    }
}