Мне нужно сделать матрицу треугольника Паскаля с использованием векторов, а затем распечатать ее.
Этот алгоритм будет работать с массивами, но почему-то он не работает с матрицей, использующей векторы.
#include <iomanip>
#include <iostream>
#include <vector>
typedef std::vector<std::vector<int>> Matrix;
int NumberOfRows(Matrix m) { return m.size(); }
int NumberOfColumns(Matrix m) {
if (m.size() != 0)
return m[0].size();
return 0;
}
Matrix PascalTriangle(int n) {
Matrix mat;
int a;
for (int i = 1; i <= n; i++) {
a = 1;
for (int j = 1; j <= i; j++) {
if (j == 1)
mat.push_back(j);
else
mat.push_back(a);
a = a * (i - j) / j;
}
}
return mat;
}
void PrintMatrix(Matrix m, int width) {
for (int i = 0; i < NumberOfRows(m); i++) {
for (int j = 0; j < NumberOfColumns(m); j++)
std::cout << std::setw(width) << m[i][j];
std::cout << std::endl;
}
}
int main() {
Matrix m = PascalTriangle(7);
PrintMatrix(m, 10);
return 0;
}
Я ничего не получаю на экране, и вот тот же код, только без матрицы с использованием векторов программа (что работает нормально).
Не могли бы вы помочь мне исправить этот код?
Я пробовал push_back
не работает
Поскольку мы не видим код с push_back
, проблема в том, что вы каким-то образом неправильно его используете. В push_back
нет абсолютно ничего плохого. Несмотря на это, текущий код, который у вас есть, не является стартовым — вы не добавляете элементы в вектор с помощью []
.
Я добавил push_back
в свой код
Ваш Matrix
имеет два векторов, а не один. Где вызов для добавления элементов во «внутренний» вектор? Таким образом, это выглядит как проблема с вашей логикой — вы должны учитывать, что у вас есть «внешний» вектор и «внутренний» вектор, о которых нужно позаботиться.
Я не знаю, как добавить элементы во «внутренний» вектор. Не могли бы вы помочь мне?
Пожалуйста, не меняйте исходный код. Добавьте новый код в качестве редактирования.
Ваш код не скомпилируется, потому что у вас много ошибок в PascalTriangle
.
Во-первых, вы инициализируете матрицу без элементов. Кроме того, вы используете матричные индексы, начинающиеся с 1, а не с 0.
Следующее печатает вещи для меня:
Matrix PascalTriangle(int n) {
Matrix mat(n, std::vector<int>(n, 0)); // Construct Matrix Properly
int a;
for (int i = 0; i < n; i++) { // Start index at 0
a = 1;
for (int j = 0; j < i + 1; j++) { // Start index at 0
if (j == 0) // Changed 1 to 0
mat[i][j] = 1;
else
mat[i][j] = a;
a = a * (i - j) / (j+1); // Changed j to j+1 since j starts at 0
}
}
return mat;
}
большое спасибо, но это не выводит правильный вывод, как здесь onlinegdb.com/LdhxIlUtL
Извините, у меня была небольшая опечатка (я только что исправил). Вам нужно зациклить j < i+1
вместо j<i
Единственная проблема заключается в том, что вы создаете матрицу n x n
, тогда как на самом деле размер может быть меньше, чем n x n
для треугольника Паскаля. Решением будет добавление данных в строку только при необходимости.
@PaulMcKenzie да, но ОП не находится в ситуации, когда ему нужно сохранять каждый байт памяти, который он может получить. В любом случае, сложность памяти одинакова.
Основная проблема заключается в том, что в PascalTriangle
вы начинаете с пустым Matrix
как в количестве строк, так и в столбцах.
Поскольку в моих комментариях упоминается push_back
, вот способ его использования, если вы не инициализировали Matrix
количеством переданных элементов.
Другая проблема заключается в том, что NumberOfColumns
должен указывать строку, а не только вектор матрицы.
Последняя проблема заключается в том, что вы должны передавать Matrix
по константной ссылке, а не по значению.
Решение всех этих проблем приводит к следующему:
Matrix PascalTriangle(int n)
{
Matrix mat;
for (int i = 0; i < n; i++)
{
mat.push_back({}); // creates a new empty row
std::vector<int>& newRow = mat.back(); // get reference to this row
int a = 1;
for (int j = 0; j < i + 1; j++)
{
if (j == 0)
newRow.push_back(1);
else
newRow.push_back(a);
a = a * (i - j) / (j + 1);
}
}
return mat;
}
А затем в NumberOfColumns
:
int NumberOfColumns(const Matrix& m, int row)
{
if (!m.empty())
return m[row].size();
return 0;
}
А потом NumberOfRows
:
int NumberOfRows(const Matrix& m) { return m.size(); }
И последнее, PrintMatrix
:
void PrintMatrix(const Matrix& m, int width)
{
for (int i = 0; i < NumberOfRows(m); i++)
{
for (int j = 0; j < NumberOfColumns(m, i); j++)
std::cout << std::setw(width) << m[i][j];
std::cout << std::endl;
}
}
есть ли способ сделать это без получения ссылки на строку? Потому что мы еще не выучили ссылки
Я получил ссылку на последнюю строку, потому что ее легче обрабатывать с точки зрения ввода и простоты использования. Например, вы могли бы использовать mat.back().push_back(1);
. И да, чтобы правильно получить последний элемент вектора, нужно использовать back()
. Если вы действительно не хотите использовать back()
, то mat[mat.size()-1].push_back(1)
будет сделано. Но что кажется вам проще и менее подвержено ошибкам?
не могли бы вы отредактировать свой код, чтобы он работал без ссылки?
На какую ссылку вы ссылаетесь? Я не буду редактировать ответ, если вы говорите о передаче Matrix
по ссылке. Это большая часть ответа, который я опубликовал.
Я говорю обо всех использованных ссылках
Я оставляю это вам, чтобы удалить ссылки. У меня есть привычка не публиковать плохой код C++. Ответы на StackOverflow должны отражать правильный стиль кодирования.
будет ли это работать, если const Matrix &m
изменится на Matrix m
?
Да, это сработает, но каждый раз, когда вы проходите Matrix m
, вы создаете временную копию всей этой матрицы. Вот почему его следует передавать по константной ссылке, чтобы не создавать временную копию. Я не знаю, исходите ли вы из Java, С# или подобного языка, но С++ по умолчанию передает нет по ссылке (как и в других языках). Важно знать разницу между прохождением Matrix m
и прохождением Matrix& m
.
так что однозначно лучше пользоваться референсами, большое спасибо, я иду с С, так же как я выучил С, так и пришел в бездонный океан С++ :)
У меня проблема с попыткой не использовать ссылку для строки... Не могли бы вы помочь мне исправить эту ошибку onlinegdb.com/ob6_QZh80: conversion from ‘void’ to non-scalar type ‘std::vector’ requested
Избавьтесь от newRow
вообще, если вы не хотите использовать ссылки, и, пожалуйста, обратитесь к моему предыдущему комментарию о mat.back()
. И ваша попытка подтверждает мою предыдущую точку зрения - какой способ проще и менее подвержен ошибкам? Странно то, что получение ссылки - это точно того, что вы пытаетесь сделать в обычном режиме, поэтому я действительно не знаю, почему вы настаиваете на выполнении 2 + 2 + 2 + 2 вместо 2 x 4.
Matrix mat;
-- Как добавить элементы в пустой вектор? Я не вижу обращений кpush_back
,insert
,emplace_back
,resize
и т. д.