Главная страница
Навигация по странице:

  • ПРИМЕР

  • 5.3. Обработка отдельных строк или столбцов матрицы

  • 5.4. Квадратные матрицы

  • N = 4 => A[0,3](i=0, j=3) j=4-0-1=3 A[1,2](i=1, j=2) j=4-1-1=2 A[2,1](i=2, j=1) j=4-2-1=1 A[3,0](i=3, j=0) j=4-3-1=0

  • В. Ю. Наумов Введение в информатику


    Скачать 2.05 Mb.
    НазваниеВ. Ю. Наумов Введение в информатику
    Анкорosnovy_prog С
    Дата13.02.2022
    Размер2.05 Mb.
    Формат файлаpdf
    Имя файлаosnovy_prog С++.pdf
    ТипДокументы
    #360392
    страница9 из 15
    1   ...   5   6   7   8   9   10   11   12   ...   15
    j). Блок-схема алгоритма представлена на рис. 5.6.

    145
    Программа будет выглядеть следующим образом: i=0; iA[ I ][ j ] % 2 ==0
    k ++
    S = S + A[ I ][ j ]
    k ≠ 0
    SrA = S/k вывод SrA
    ‘В массиве нет четных элементов’
    Ввод A[ I ][ j ]
    i=0; iВвод N, M
    Начало
    Конец
    J=0; jJ=0; jРис. 5.6. Среднее арифметическое четных элементов двумерного массива

    146
    #include int main()
    { int n,m,a[10][15]; cout<<”\nInput count of rows”; cin<>m; for (int i=0; i { cout<<”\na[“<>a[i][j];
    } int s=0, k=0; for (int i=0; i { k++; s+=a[i][j];
    } if (k!=0)
    { float sra=float(s)/float(k); cout<<”\nsra=”< } else cout<<”\n The array is not even elements”;
    }
    Поэлементная обработка массива с анализом может быть представлена некоторыми классическими алгоритмами. Наиболее известные и часто встречающиеся – алгоритмы поиска экстремальных по значению (максимум и минимум). Итак, для примера рассмотрим поиск максимума в двумерном массиве. Алгоритм точно такой же, как и для одномерного массива. Стоит только не забывать, что при просмотре меняются как строки, так и столбцы. Кроме того, необходима пара индексов для выяснения точного местоположения элемента с максимальным значением. За координаты отвечают переменные IMax,
    JMax, а за сам максимум переменная Max (рис. 5.7):

    147 int imax=0, jmax=0, max=a[0][0]; for (int i=0; imax)
    { max=a[i][j]; imax=i; jmax=j;
    }
    Очевидно, что для поиска минимального элемента потребуется изменить знак в условии с «>» на «<», а имена переменных, в которых будут храниться искомые значения, следует заменить на IMin, JMin и Min. i=0; iMax = A[0][0]
    j=0; jA[i][j] > Max
    Max = A[i][j]
    IMax = i
    JMax = 0
    IMax = 0
    JMax = j

    148
    Алгоритмы поиска элементов не всегда могут быть такими простыми. В качестве примера рассмотрим еще одну задачу, которая решалась для одномерного массива.
    ПРИМЕР
    Найти наименьший среди нечетных элементов двумерного массива.
    Составим тестовый пример:
    вход:
    8 1
    3 1
    5 0
    7 6
    2 1
    9 4
    A



     
    выход: Min = –5; IMin = 1; JMin = 0;
    Здесь при решении есть некоторые особенности, связанные с тем, что обрабатываемый массив двумерный. А в целом алгоритм практически такой же, как и в предыдущей задаче, и распадается на две части: поиск первого нечетного элемента и поиск минимума, при условии нечетности, начиная с найденного. Тут тоже воспользуемся для первой части задачи циклом с предусловием. Теперь нужно производить инкрементацию не только индекса столбца JMin, но и следить за своевременной инкрементацией индекса столбца IMin (рис. 5.8):

    149 j=0; jA[i, j] < A[Imin, JMin]
    && A[i, j]%2!=0
    IMin = i
    A[IMin, JMin]%2==0
    && IminJMin ++
    IMin = 0
    JMin = 0
    i=imin; iJMin = j
    Jmin==M
    JMin = 0
    IMin ++
    IminВывод A[IMin, Jmin]
    IMin, JMin
    ‘В массиве все элементы четные’
    Рис. 5.7. Поиск минимального среди нечетных

    150 int im in=0, jmin=0 while (A[imin,jmin]%2==0 && imin{ jmin++; if (jmin==m) then
    { jmin=0; imin++;
    }
    } for (int i=0; i { min=a[i][j]; imin=i; jmin=j;
    } if (iminЕсли в массиве все элементы четные, то будет выведено соответствующее сообщение. Рассмотренный пример является одним из вариантов решения задачи (однако он не единственный). Есть иная реализация алгоритма поиска с использованием логической переменной
    Flag, аналогично тому как это делалось для одномерного массива. Здесь будет все аналогично, за исключением добавления цикла по строкам и включения как индексов строк, так и столбцов (алгоритм рассматривать не будем).
    Вот еще одна типовая задача на максимумы и минимумы для двумерных массивов.
    ПРИМЕР
    В двумерном массиве поменять местами максимальный и
    минимальный элементы.
    Тут все просто. Ищем индексы максимума и минимума, а далее производим обмен в три действия (рис. 5.9).

    151
    #include int main()
    { int n,m,a[10][15]; cout<<”\nInput count of rows”; cin<>m; for (int i=0; i { cout<<”\na[“<Начало
    Конец i=0; ij=0; jВвод A[i][j]
    i=0; ij=0; jВывод A[i, j]
    i=0; iimax=0; jmax=0;
    imin=0; jmin=0;
    j=0; jA[i][j]>A[imax][jmax]
    imax=i;
    jmax=j;
    A[i][j]imin=i;
    jmin=j;
    buf = A[imax][jmax]
    A[imax][jmax]=
    A[imin][jmin]
    A[imin][jmin] = buf
    2 1
    1 2
    Ввод n,m
    Рис. 5.8. Обмен максимума и минимума в двумерном массиве

    152 cin>>a[i][j];
    } int imax=0, jmax=0, imin=0, jmin=0; for (int i=0; i { if (a[i][j] > a[imax][jmax])
    { imax=i; jmax=j;
    } if (a[i][j] < a[imin][jmin])
    { imin=i; jmin=j;
    }
    } int buf=a[imax][jmax]; a[imax][jmax]=a[imin][jmin]; a[imin][jmin]=buf; for (int i=0; i { cout<<”\n”; for (int j=0; j }
    }
    ПРИМЕР
    Далее можно рассмотреть задачу формирования из заданного массива нового.
    Из матрицы A получить новые одномерные массивы C и D. В C
    содержатся положительные компоненты матрицы A, а в D
    отрицательные. Длины получившихся массивов сохраняются в переменных
    Nc и Nd соответственно.
    Тестовый пример может выглядеть так:
    вход:
    1 5
    4 2
    3 3
    0 6
    7 0
    8 0
    A

     
    выход:
    1 4
    2 3
    6 7
    8 5
    3
    B
    D

     

    Листинг программы для блок-схемы (рис. 5.10): int nc=0, nd=0,c[15],d[15]; for (int i=0; i

    153 if (a[i][j]>0)
    { c[nc]=a[i][j]; nc++;
    } else
    { d[nd]=a[i][j]; nd++;
    }
    5.3. Обработка отдельных строк или столбцов матрицы
    Важным классом алгоритмов обработки двумерных массивов является построчная или постолбцовая обработка. Если вспомнить одно из
    A[i][j] > 0
    j=0; jC[nc] = A[i][j]
    nd=0;
    nc++
    A[i][j] < 0
    D[nd] = A[i][j]
    nd++
    i=0; inc=0;
    Рис. 5.9. Формирование из двумерного массива пары одномерных

    154 определений двумерного массива, которое говорит, что это «массив одномерных массивов», то подход к поставленной задаче упрощается.
    Для решения таких задач можно воспользоваться алгоритмами показанными на рис. 5.11. Суть их сводится к тому, что внутри внешнего цикла помещаются действия, которые можно представить в виде алгоритма на одномерном массиве, если положить неизменным индекс строки i при построчном, или индекс j при постолбцовом проходе.
    В качестве примера можно решить, скажем, такую задачу:
    ПРИМЕР
    Найти сумму положительных элементов в каждой строке
    матрицы.
    Алгоритм решения состоит в следующем. Во внешнем цикле меняем индекс строки (рис. 5.12, а), а во внутреннем – решаем задачу поиска суммы элементов одномерного массива с последующим выводом результатов на экран (рис. 5.12, б). Индекс строки i фиксируем во внутреннем цикле. Поиск суммы обычный, по рекуррентной формуле:
    «сумма текущего равна накопленной сумме на предыдущем, плюс текущее». На каждом новом проходе (при изменении индекса строки i) происходит обнуление переменной, хранящей текущее значение суммы S.
    Для иллюстрации задачи предоставим тестовый пример: i=0; iАлгоритм обработки i- й строки j=0; jАлгоритм обработки j- го столбца а)
    б)
    Рис. 5.10. Построчная (а) и постолбцовая (б) обработка двумерного массива

    155
    вход:
    1 4
    8 0
    2 1
    0 4
    5 3
    2 7
    1 0
    8
    A








    выход:
    1 2
    3 0
    8 10
    S
    S
    S



    Программная часть на языке C++ следующая: for (int i=0; i{ int s=0; for (int j=0; j0) s=s+a[i][j]; cout<<”\ni=”<}
    А теперь рассмотрим пример с обработкой элементов по столбцам.
    ПРИМЕР
    Переписать максимальные элементы каждого столбца двумерного
    массива A в одномерный массив B.
    Тестовый пример выглядит так: i=0; iПоиск и вывод суммы в i-ой строке а)
    б)
    j=0; jA[i][j] > 0
    S= S + A[i][j]
    S= 0
    Вывод S
    1 2
    шаг 1-2
    Рис. 5.11. Поиск суммы положительных элементов в каждой строке

    156
    вход:
    1 4
    8 0
    2 1
    0 4
    5 3
    2 7
    1 0
    8
    A








    выход:
    2 0
    4 0
    8
    B

    ,
    Текст программы: int b[m]; for (int j=0; j{ int max=a[0][j]; for (int i=0; imax) max=a[i][j]; b[j]=max;
    }
    Можно рассмотреть еще одну подобную задачу, а именно:
    ПРИМЕР
    Отсортировать по возрастанию каждую строку матрицы, то есть: j=0; jФормирование элемента B[ j ]
    а)
    б)
    i=0; iA[i][j] > Max
    Max = A[i][j]
    Max = A[0][j]
    1 2
    шаг 1-2
    B[ j ] = Max
    Рис. 5.12. Поиск максимума в каждом столбце

    157
    вход:
    1 4
    8 0
    2 1
    0 4
    5 3
    2 7
    1 0
    8
    A








    выход:
    8 4
    2 1
    0 5
    0 1
    3 4
    7 1
    0 2
    8
    A




     


    Для решения нужно вспомнить, как происходила сортировка одномерного массива. Ведь каждая строка в матрице, по сути,– одномерный массив. Потому, если опять воспользоваться разбивкой алгоритма на детали, то решение достаточно простое. Во внешнем цикле меняется индекс строки (рис. 5.14, а), а во внутреннем – происходит сортировка строки по индексу столбца j. В качестве метода сортировки возьмем пузырьковый.
    Видно, что алгоритм практически точно повторяет тот, который мы использовали для одномерного массива (рис. 5.14, б). Стоит обратить внимание на тот факт, что при решении данной задачи возникают циклы k=m-1; k>1; k-- j=0; jA[i][j] > A[i][j+1]
    buf = A[i][j]
    A[i][j]= A[i][j+1]
    A[i][j+1] = buf i=0; iСортировка i-й строки а)
    б)
    1 2
    шаг 1-2
    Рис. 5.13. Сортировка каждой строки матрицы

    158 двойной степени вложенности, т. е. задача решается в три цикла. Вот текст алгоритма на C++: for (int i=0; i1; k--) for (int j=0; ja[i][j+1])
    { int buf = a[i][j]; a[i][j] = a[i][j+1]; a[i][j+1] = buf;
    }
    Для обработки элементов двумерного массива, на строки которого накладываются некоторые условия, нужно при просмотре этого массива внутрь циклов ставить условие не на элемент, а на индекс строки или столбца (в зависимости от условия задачи).
    ПРИМЕР
    Заполнить единицами каждый второй столбец матрицы, то есть
    вход:
    1 4
    8 0
    2 1
    0 4
    5 3
    2 7
    1 0
    8
    A








    выход:
    4 1
    0 1
    2 0
    1 5
    1 3
    7 1
    0 1
    8
    A





    Вот алгоритм с условием на индекс столбца (рис. 5.15, а): for (int j=0; jОчевидно, что приведенный способ решения обладает недостатком, заключающимся в том, что число проходов по массиву вдвое больше чем число четных столбцов. Число проходов можно сократить в два раза, если рассматривать только четные столбцы (рис. 5.15, б). for (int j=0; j

    159
    Вообще, там, где происходит заведомо меньшее число проходов чем строк или столбцов в матрице, нет необходимости проводить полный перебор. Гораздо логичнее будет использовать или цикл с предусловием с нужным шагом по строкам/столбцам, или цикл for с меньшим числом проходов и с формулой прямого вычисления нужного индекса.
    ПРИМЕР
    Переставить местами соседние столбцы матрицы. Это означает следующее:
    вход:
    1 4
    8 0
    2 1
    0 4
    5 3
    2 7
    1 0
    8
    A








    выход:
    4 1
    0 8
    2 0
    1 5
    4 3
    7 2
    0 1
    8
    A








    Последний столбец остался без изменения, поскольку для него не нашлось пары. Очевидно, что число парных перестановок столбцов в два раза меньше, чем их количество в матрице.
    Алгоритм решения при помощи цикла for следующий (рис. 5.16, а): j=0; jа)
    i=0; iA[i][j] = 1
    j % 2 == 0
    j=0; jб)
    i=0; iA[i][j] = 1
    Рис. 5.14. Обработка четных столбцов матрицы: при помощи цикла for а – с шагом 1; б – с шагом 2

    160 for (int j=0; j { int buf = a[i][j*2-1]; a[i][j*2-1] = a[i][j*2]; a[i][j*2] = buf;
    }
    А если воспользоваться циклом while, то выглядеть это будет так
    (рис. 5.16, б): int j=0; while (j{ for (int i=0; i { int buf = a[i][j+1]; j=0; jj < m j = j + 2
    j = 0
    а)
    б)
    i=0; ii=0; iA[i][j*2] = buf
    A[i][j*2-1] = A[i][j*2]
    buf = A[i][j*2-1]
    A[i][j] = buf
    A[i][ j+1] = A[i][j]
    buf = A[i][j+1]
    Рис. 5.15. Перестановка столбцов в матрице: при помощи цикла for (а); при помощи цикла while (б)

    161 a[i][j+1] = a[i][j]; a[i][j] = buf;
    } j=j+2;
    }
    5.4. Квадратные матрицы
    Достаточно интересным и важным классом двумерных массивов являются квадратные. Квадратные матрицы – это такие матрицы, у которых число элементов в строке равно числу элементов в столбце, т. е.
    M=N.
    В квадратных матрицах выделяют некоторые особенные групп-пы элементов. Это, прежде всего, главная и побочная диагонали.
    Особенностью элементов на главной диагонали является тот факт, что для каждого из них индекс строки равен индексу столбца, т. е. i==j.
    Если внимательно посмотреть на рис. 5.17, то можно вывести правило принадлежности элемента к побочной диагонали. Это правило можно выразить формулой для индексов j == N – i - 1.
    Для матрицы, изображенной на рис. 5.17, это действительно так.
    Покажем это:
    N = 4 =>
    A[0,3](i=0, j=3) j=4-0-1=3
    A[1,2](i=1, j=2) j=4-1-1=2
    A[2,1](i=2, j=1) j=4-2-1=1
    A[3,0](i=3, j=0) j=4-3-1=0
    Если смотреть на элементы диагоналей, то видно что они похожи на одномерные массивы, расположившиеся вдоль диагоналей. Потому для их обработки достаточно одного цикла.
    0,0 0
    0,1 1
    0,2 2
    1,0 1,1 1,2 2,0 2,1 2,2 0
    1 2
    Главная диагональ
    Побочная диагональ
    0,3 1,3 2,3 3,0 3,1 3,2 3,3 3
    3
    Рис. 5.16. Диагонали в матрице

    162
    ПРИМЕР
    Найти среднее арифметическое отрицательных элементов главной
    диагонали.
    Решение таково (рис. 5.18): int k=0, s=0; for (int i=0; i { i=0; iA[i][i] < 0
    k ++
    S = S + A[i][i]
    ‘На гл. диагонали нет отриц. элементов’
    k = 0
    S = 0
    k != 0
    SrA = S/k
    Вывод SrA
    Рис. 5.17. Среднее арифметическое отрицательных элементов главной диагонали

    163 k++; s=s + a[i][i];
    } if (k!=0)
    { float sra=(float)S/(float)k; cout<<”\nsra=”<} else cout<<”\nOn the main diagonal are no negative elements”;
    А теперь рассмотрим такую задачу:
    ПРИМЕР
    Обменять элементы главной и побочной диагоналей местами.
    Обмен происходит следующим образом:
    вход:
    4 2
    8 9
    3 6
    0 1
    6 7
    8 0
    5 3
    2 1
    A

    выход:
    9 2
    8 4
    3 0
    6 1
    6 8
    7 0
    1 3
    2 5
    A

    Алгоритм простой (рис. 5.19): for (int i=0; i{ int buf = a[i][i]; a[i][i] = a[i][N-i+1]; a[i][N-i+1] = buf;
    }
    Далее к особенным элементам стоит отнести верхний и нижний треугольники. Нижним треугольником называют главную диагональ и элементы под нею. Верхним треугольником называют главную диагональ и элементы над нею. Треугольники в матрице показаны на рис. 5.20.
    Условие нахождения элемента в нижнем треугольнике такое: i≥j. Для верхнего треугольника неравенство обратное: i≤j. i=0; ibuf = A[i][i]
    A[i][i] = A[i][N-i+1]
    A[i][N-i+1] = buf
    Рис. 5.18. Обмен диагоналей

    164
    Кроме элементов над и под главной, выделяют также элементы над и под побочной диагональю. Условие нахождения над побочной диагональю такое: j, а под побочной такое: j>N-i-1.
    Для обработки элементов из треугольников матриц можно пользоваться двумя способами.
    0,0 0
    0,1 1
    0,2 2
    1,0 1,1 1,2 2,0 2,1 2,2 0
    1 2
    0,3 1,3 2,3 3,0 3,1 3,2 3,3 3
    3 0,0 0
    0,1 1
    0,2 2
    1,0 1,1 1,2 2,0 2,1 2,2 0
    1 2
    0,3 1,3 2,3 3,0 3,1 3,2 3,3 3
    3
    i≥j i≤j
    Рис. 5.19. Нижний и верхний треугольники в матрице i=0; ik = 0
    j=0; ji
    ≥ j && A[i][j]==0
    k ++
    Рис. 5.20. Обработка нижнего треугольника с условием на индексах

    165
    Первый заключается в просмотре всех элементов с последующей проверкой условия принадлежности индексов элемента тому или иному треугольнику. Такой способ более надежен, однако зря расходует системные ресурсы, просматривая всю матрицу целиком. Треугольник – это примерно половина матрицы. Для более рационального использования ресурсов можно иначе задать границы изменения циклов. Однако, в этом случае больше вероятность риска ошибиться.
    1   ...   5   6   7   8   9   10   11   12   ...   15


    написать администратору сайта