- •Часть 2
- •18 Сентября 2012 г., протокол № 1
- •Предисловие
- •Глава 6 простые типы данных § 1. Целый тип
- •1.1. Битовые операции
- •Использование битовых операций
- •1.3. Упаковка и распаковка информации
- •§ 2. Логический тип
- •§ 3. Символьный тип
- •§ 4. Вещественный тип
- •§ 5. Преобразование типов
- •Преобразование типов в выражениях
- •Преобразование типов при присваивании
- •Г л а в а 7 введение в указатели
- •§ 1. Понятие указателя. Операции разыменования и разадресации
- •§ 2. Инициализация и присваивание указателей
- •§ 3. Распределение динамической памяти
- •Операция new
- •Операция delete
- •§ 4. Параметры-указатели. Функция ввода scanf
- •Упражнения, тесты
- •Г л а в а 8 одномерные массивы, указатели и функции
- •§ 1. Связь указателей и одномерных массивов. Передача массива в качестве параметра функции
- •§ 2. Сортировка одномерных массивов
- •§ 3. Сортировка массива по параметру числа
- •§ 4. Сортировка массива выбором.
- •§ 5. Сортировка массива вставками
- •§ 6. Динамические одномерные массивы
- •6.1. Порядок работы с динамическим массивом
- •6.2. Работа с динамическим массивом в классе. Деструктор
- •§ 7. Введение в строки
- •Глава 9 мАтрицы
- •§ 1. Объявление, способы определения матриц
- •§ 2. Вывод матриц
- •§ 3. Типы алгоритмов
- •3.1. Построчная обработка
- •Обработка матрицы по столбцам
- •3.3. Обработка всей матрицы
- •3.4. Обработка части матрицы
- •Преобразование матрицы
- •Построение матриц
- •§ 4. Матрицы, указатели и функции
- •Упражнения и тесты
- •Обработка матрицы по столбцам.
- •Список реКоМендуемой литературы
- •Сборники задач по программированию
- •Оглавление
- •Методы программирования:
- •Лекции, примеры, тесты
- •Пособие для студентов механико-математического факультета
- •В двух частях
- •Часть 2
Преобразование матрицы
Пример 13. Перестановка двух строк, номера n1 и n2 которых извстны, выполняется следующим образом. Составим функцию для перестановки двух целых чисел: void RR( int &x, int &y) { int t=x; x=y; y=t; }
В другой функции или в main выполняем поэлементную перестановку каждой пары элементов: for (int j=0; j<m; j++) RR( A[n1][ j] , A[n2][j]);
В качестве упражнения с помощью той же функции выполните перестановку m1–го и m2–го столбцов, если m1 и m2 заданы.
Пример 14. Удаление k–й строки, где k известно.
for (int i=k; i<n-1; i++)
for (int j=0; j<m; j++) A[i][j]=A[i+1][j];
Здесь на место k–й строки помещаем каждый элемент (k+1)–й строки, на место (k+1)–й — (к+2)–ю строку и так далее. Наконец, на место (n-2)–й копируем (n-1)–ю строку. Таким образом, все строки, начиная с (к+1)–й, “поднимаем на одну вверх”. Но объём зарезервированной памяти для матрицы не изменяется, то есть физически ни одну строку из памяти мы не удаляли. Но после “удаления” одной строки количество обрабатываемых строк надо на одну уменьшить. Последняя строка в обработке уже не должна участвовать. Например, выводить надо (n-1) строку.
Пример 15. Для вставки одной строки после к-й на первом этапе необходимо все строки с n–й до (к+1)-й в обратном порядке “опустить вниз”:
for (int i=n; i>=k+1; i--)
for (int j=0; j<m; j++) A[i+1][j]=A[i][j];
Затем на место освободившейся (k+1)–й строки надо поместить вставляемую строку, например, одномерный введённый массив B такой же размерности m, что и строка матрицы:
for (int j=0; j<m; j++) A[k+1][j]=B[j];
При объявлении матрицы необходимо учесть, что после вставки количество строк увеличится. Поэтому если по условию вставляется одна строка, то объявляем её так: int A[n+1][m]. Если после каждой строки с некоторым условием, например, после строк, у которых больше половины нулей, надо вставить новую строку, то матрицу объявляем так: int A[2*n][m];. Реально такой вариант будет маловероятным и память будет использоваться неэффективно.
Похожая проблема с памятью имеет место и при удалении строк. Более того, если перестановку, удаление или вставку строк надо выполнять несколько раз, то для больших матриц может возникнуть проблема и со временем выполнения программы. Поэтому на практике такое преобразование эффективнее выполнять с помощью динамических матриц или списков, которые будут изучены позже.
Построение матриц
Выделим некоторые подтипы таких задач.
1. Элементы матрицы зависят от своих же индексов, т. е. от номера строки и (или) столбца.
Пример 16 (см. пример 3). Построить матрицу по правилу Aij = (i+1)*(j+1);
При построении матрицы используется одно число.
Пример 17. Для заданных значений x и n построить квадратную матрицу размерности n:
1 x x2 x3 … xn-1
x 0 0 0 … xn-2
x2 0 0 0 … xn-3
… … … … … …
xn-1 xn-2 xn-3 x… 1
Предлагается следующий алгоритм. Очередной элемент “периметра” матрицы получаем так: умножаем предыдущий элемент на x и помещаем его в первую и последнюю строки, в первый и последний столбцы. Для этого достаточно одного цикла. const n=5; float A[n][n], x, T=1;
cin>> x; /* Ввели только одно число */
A[0][0]= A[n-1][n-1]=1;
for (int i=1; i<n; i++) { T*=x;
A[0][i]= // элементы 0–й строки,
A[i][0]= // элементы 0–го столбца,
A[n-1][n-1-i]= // элементы (n-1) –й строки,
A[n-1-i][n-1]= T; } // элементы (n-1) –го столбца
/* Все “центральные” элементы обнуляем */
for (int i=1; i<n-1; i++)
for (int j=1; j<n-1; j++) A[i][j]=0;
3. Матрицу можно построить, используя один или несколько одномерных массивов.
Пример 18. Дан одномерный массив b[n]. Построить матрицу A[n][m] по следующему правилу:
b0 b0+1 b0+2 … b0 +(m-1)
b1 b1+1 b1+2 … b1 +(m-1)
… … … …
bn-1 bn-1 +1 bn-1 +2 bn-1 +(m-1).
В таких задачах необходимо установить, от чего и как зависят индексы элементов матрицы и, возможно, значения её элементов. Получаем
for (int i=0; i<n; i++)
for (int j=0; j<m; j++) A[i][j]=b[i]+j;
4. Новая матрица строится на основе одной или нескольких определённых к этому времени матриц.
Пример 19. Из вещественной матрицы С[n][m]. получить новую матрицу такой же размерности A[n][m] по правилу: положительные числа исходной матрицы увеличим в 10 раз, а отрицательные уменьшим в 10 раз:
for (int i=0; i<n; i++)
for (int j=0; j<m; j++)
{ t= C[i][j]; A[i][j] = t>0 ? t*10 : t/10; }
Заметим, что старая матрица С не изменилась, а построенная разместилась на новом месте.
Следует отличать такую задачу от задачи, в которой исходная матрица преобразуется, а изменённые её значения сохраняются на том же месте. Для решения в такой постановке достаточно с помощью тех же циклов записать
t= C[i][j]; С[i][j] = t>0 ? t*10 : t/10;. В таком варианте матрица С задана, она же в результате преобразований изменяется, то есть новые значения заменяют старые на том же месте оперативной памяти. Новая матрица А в таком случае не нужна.
Этот параграф, безусловно, не претендует на полное исследование всех типов матричных алгоритмов. Приведены основные наиболее простые из них, которые можно использовать при начальном изучении программирования с минимальным знанием математической теории матриц. Более сложные задачи состоят, как правило, из отдельных рассмотренных выше “кирпичиков”.
