Отсортировать элементы матрицы - 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.

Объяснение кода листинга программы

  1. Объявляются глобальная константа m со значением 10, и глобальные переменные n, tn, gi, gj типа целое число, и a - массив целых чисел размером m на m.
  2. Происходит определение процедуры gen, которая инициализирует значения массива a случайными числами.
  3. Определяется процедура prn для печати значений элементов массива.
  4. Функция gij получает индексы массива по числу k в хитрой змейке.
  5. Реализуется рекурсивная функция hoar для быстрой сортировки, с использованием хитрой змейки для доступа к элементам массива.
  6. В основном блоке программы инициализируется генератор псевдослучайных чисел, происходит ввод размера массива, инициализация массива, печать исходного массива, вычисление треугольного числа и сортировка массива при помощи функции hoar, вывод отсортированного массива. Note: Последующий код приведен в языке Pascal.

ИИ поможет Вам:


  • решить любую задачу по программированию
  • объяснить код
  • расставить комментарии в коде
  • и т.д
Попробуйте бесплатно

Оцени полезность:

15   голосов , оценка 4.067 из 5
Похожие ответы