- •История изменений
- •Благодарности
- •Основы
- •Привет, Мир!
- •Ввод-вывод
- •Целые числа
- •Символы и строки
- •Перевод целого числа в строку
- •Случайные числа
- •String
- •Перевод строки в целое число
- •Профилирование
- •Массивы и матрицы
- •Объявление, размещение и инициализация массивов
- •Ввод массива
- •Вывод массива
- •Valarray
- •Vector
- •Матрицы
- •Элементарные алгоритмы
- •Абсолютное значение целого числа
- •Минимум и максимум среди двух чисел
- •Минимум и максимум среди трёх чисел
- •Сортировка массива из трёх чисел
- •Циклический сдвиг массива из трёх элементов
- •Разложение целого числа на его цифры
- •Линейный поиск
- •Рекурсия
- •Более сложные алгоритмы
- •Бинарный поиск
- •Циклический сдвиг массива
- •Подводные камни
- •Диграфы и триграфы
Симоненко Евгений А. Олимпиадная подготовка по программированию |
19 |
valarray<int> c(n); c = a + b;
for (int i = 0; i < c.size() - 1; i++) { cout << c[i] << " ";
}
cout << c[c.size() - 1] << endl; cout << c.sum();
return 0;
}
VECTOR
Ещё более гибкой является структура данных под названием vector. Подробности оставляю читателю для самостоятельного изучения, замечу лишь то, что это одна из самых востребованных частей стандартной библиотеки C++.
МАТРИЦЫ
В C++ при создании двумерных (и более) массивов нужно заранее знать размерность. Если максимальный размер массива известен и он относительно небольшой, то его можно объявить так (во всех примерах этого пункта n – количество строк, m – количество элементов в строке:
#include <iostream>
using namespace std;
int main(int argc, char* argv[]) { const int N = 100;
const int M = 200; int matrix[N][M]; int n = 0, m = 0; cin >> n >> m;
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) { cin >> matrix[i][j];
}
}
return 0;
}
Проблемой этого подхода является то, что создать массив 1000 x 1000 уже не получится, сработает проверка на размер стека. Обусловлено это тем, что память под переменные, объявленные внутри блока, выделяется в стеке. Решение этой проблемы может стать объявление массива глобальным:
#include <iostream>
using namespace std;
const int N = 1000; const int M = 2000; int matrix[N][M];
int main(int argc, char* argv[]) { int n = 0, m = 0;
cin >> n >> m;
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) { cin >> matrix[i][j];
}
}
return 0;
}
Но этот способ может не подходить, если нужен именно локальный массив.
При m < M память, отводимая под второе измерение (под строки матрицы) будет использоваться не полностью (между соседними строками будут промежутки), что при построчной обработке мат-
20 |
Симоненко Евгений А. Олимпиадная подготовка по программированию |
рицы может приводить к потере процессорного времени (перезагрузка кэш-памяти). Можно создавать массив динамически. Например, так:
#include <iostream>
using namespace std;
int main() {
int n = 0, m = 0; cin >> n >> m;
int **a = new int* [n];
for (int i = 0; i < n; i++) { a[i] = new int[m];
for (int j = 0; j < m; j++) { cin >> a[i][j];
}
}
for (int i = 0; i < n; i++) { a[i][i] = 0;
}
for (int i = 0; i < n; i++) {
for (int j = 0; j < m - 1; j++) { cout << a[i][j] << ' ';
}
cout << a[i][m - 1]; if (i != (n - 1)) { cout << endl;
}
}
cout << endl;
for (int i = 0; i < n - 1; i++) { cout << a[i] << endl; delete[] a[i];
}
cout << a[n - 1]; delete[] a[n - 1]; delete[] a;
return 0;
}
Здесь двумерный массив создаётся динамически с помощью new как одномерный массив указателей на одномерные массивы. Проблема этого способа в том, что последовательный вызов new не гарантирует нам, что строки матрицы будут упорядочены и без промежутков, что и подтверждает вывод этой программы.
Проблему промежутков можно решить следующим способом:
#include <iostream>
using namespace std;
int main(int argc, char *argv[]) { int n = 0, m = 0;
cin >> n >> m;
int *a = new int[n * m]; #define a(i,j) a[m * (i) + (j)] for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) { cin >> a(i,j);
}
}
for (int i = 0; i < n; i++) { a(i,i) = 0;
}
for (int i = 0; i < n; i++) {
for (int j = 0; j < m - 1; j++) { cout << a(i,j) << ' ';
}
cout << a(i,m - 1); if (i != (n - 1)) {
