Отсортировать элементы матрицы - Pascal
Формулировка задачи:
Дано натуральное N (1 ≤ N ≤ 10), целочисленный квадратный массив-матрица (aij), 0 ≤ i ,j < N. Отсортировать элементы матрицы так, чтобы при прохождении по схеме они были бы упорядочены по не убыванию. Методом быстрой рекурсивной сортировки.
Змейка из двух частей: вначале сверху вниз по строкам «вправо-влево» до побочной диагонали матрицы, потом снизу вверх по строкам «вправо-влево» от побочной диагонали матрицы.
Важное ограничение. При сортировке элементов матрицы не разрешается использовать дополнительные структуры данных (массивы), то есть вся сортировка должна производиться «на месте» – в исходном массиве. Кроме этого нужно сохранить временную сложность алгоритма сортировки: другими словами нельзя вводить дополнительных циклов (например, для вычисления координат) по сравнению с теми, что уже есть в сортировке.
Листинг программы
- 0 1 2 3
- 6 5 4 15
- 7 8 14 13
- 9 10 11 12
Решение задачи: «Отсортировать элементы матрицы»
textual
Листинг программы
- //глобальные константа и переменные: видны и в программе, и во всех подпрограммах
- const m = 10; //максимальный размеры массива
- var n, tn, gi, gj: integer; //размер массива, треугольное число, индексы массива
- a: array [0..m-1, 0..m-1] of integer; //массив
- //процедура генерации массива (можно при желании заменить процедурой ввода)
- procedure gen(n: integer);
- var i, j: integer;
- begin
- for i := 0 to n - 1 do
- for j := 0 to n - 1 do a[i, j] := -99 + random(199)
- end;
- //процедура печати массива,
- //параметры: s - заголовок, n - размер массива
- procedure prn(s: string; n: integer);
- var i, j: integer;
- begin
- writeln(s);
- for i := 0 to n - 1 do
- begin
- for j := 0 to n - 1 do write(a[i, j]: 4);
- writeln
- end
- end;
- //функция получения индексов массива, возвращает i, а также i и j в глобальных переменных
- //параметр: номер элемента в "хитрой змейке"
- //возвращаемые значения: i в gij и в gi, j в gj
- //например, a[gij(x), gj]
- // ^ ^
- //сначала функция вычисляет i и j и возвращает i -+ |
- //теперь j (и i тоже) вычислены, можно использовать j ---+
- function gij(k: integer): integer;
- var p, v: integer; //номер строки с треугольным числом, верхняя граница треугольника
- w: boolean; //флаг нижнего треугольника
- begin
- w := k >= tn; //определяем, который треугольник
- if w //если нижний треугольник
- then v := n * n //то граница - последний номер элемента
- else v := tn; //иначе граница - треугольное число
- p := v - 1 - k; //вычисляем номер строки
- gi := trunc(sqrt(1 + 8 * p) - 1) div 2; //индекс i
- gj := p - gi * (gi + 1) div 2; //индекс j
- if odd(n - gi) then gj := gi - gj; //коррекция gj для чётного n-1-i
- if w then gj := n - 1 - gj; //коррекция j для нижнего треугольника
- inc(gi); //общая коррекция i
- if not w then gi := n - gi; //коррекция i для верхнего треугольника
- gij := gi //сама функция возвращает i (а ещё дублирует i и помещает j в глобальные переменные gi и gj)
- end;
- //рекурсивная функция быстрой сортировки (она же - сортировка Хоара)
- //параметры: границы сортировки в виде номеров "хитрой змейки"
- procedure hoar(l, r: integer);
- var i, j, x, y: integer; //текущие границы в "хитрой змейке", середина этого интервала, буферная переменная
- begin
- i := l; //сохраняем текущие границы
- j := r;
- x := a[gij((l + r) div 2), gj]; //вычисляем середину
- repeat //цикл сортировки в пределах текущих границ
- while a[gij(i), gj] < x do inc(i); //если элемент нижней границы меньше элемента средней, то отсортировано, увеличиваем нижнюю границу
- while x < a[gij(j), gj] do dec(j); //если элемент верхней границы больше элемента средней, то отсортировано, уменьшаем верхнюю границу
- if i <= j //если индексы не пересеклись,
- then begin //то
- if a[gij(i), gj] > a[gij(j), gj] //если элементы на границах не в том порядке,
- then begin
- y := a[gij(j), gj]; //то меняем их местами
- a[gij(j), gj] := a[gij(i), gj];
- a[gi, gj] := y
- end;
- inc(i); //увеличиваем границы, по-любому за границами уже отсортировано
- dec(j)
- end;
- until i >= j; //если границы встретились или поменялись местами, то сортировка текущего интекрвала закончена
- if l < j then hoar(l, j); //если j больше нижней границы, рекурсивный вызов сортировки интервала от нижней границы до j
- if i < r then hoar(i, r); //если i меньше нижней границы, рекурсивный вызов сортировки интервала от i до нижней границы
- end;
- begin
- randomize; //инициализация ГПСЧ
- repeat //ввод размера массива с проверкой
- write('n in [1..', m, ']; n = ');
- readln(n)
- until n in [1..m];
- gen(n); //генерация массива
- prn('Исходный массив:', n); //печать исходного массива
- tn := n * (n + 1) div 2; //вычисление треугольного числа для последней строки массива
- hoar(0, n * n - 1); //сортировка массива
- prn('Отсортированный массив:', n); //вывод отсортированного массива
- readln
- end.
Объяснение кода листинга программы
- Объявляются глобальная константа
m
со значением 10, и глобальные переменныеn
,tn
,gi
,gj
типа целое число, иa
- массив целых чисел размеромm
наm
. - Происходит определение процедуры
gen
, которая инициализирует значения массиваa
случайными числами. - Определяется процедура
prn
для печати значений элементов массива. - Функция
gij
получает индексы массива по числуk
вхитрой змейке
. - Реализуется рекурсивная функция
hoar
для быстрой сортировки, с использованиемхитрой змейки
для доступа к элементам массива. - В основном блоке программы инициализируется генератор псевдослучайных чисел, происходит ввод размера массива, инициализация массива, печать исходного массива, вычисление треугольного числа и сортировка массива при помощи функции
hoar
, вывод отсортированного массива. Note: Последующий код приведен в языке Pascal.
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д