Имеется матрица N X 2, представленная в одномерном массиве, который вы хотите преобразовать в массив 2 X N.
Например, ваш список:
a 1 , b 1 , a 2 , b 2 , ... a n, б н
можно также представить в виде матрицы:
x 1,1 , x 1,2 , x 2,1 , x 2,2 , ... x n, 1 , x n, 2
которым вы хотите транспонировать, чтобы стать:
x 1,1 , x 2,1 , ... x n, 1 , x 1,2 , x 2,2 , ... x n, 2
Алгоритм транспонирования матрицы на месте выполнит эту работу.
EDIT
Хорошо, позвольте мне объяснить это. Попробуйте следующий фрагмент кода:
i = 0 /* linear array index */
do j = 1 to c /* j = 1 to virtural columns */
do k = 1 to r /* k = 1 to virtural rows */
i = i + 1
sp = (k - 1) * c + j
do while sp < i
ct = (sp - 1) % r + 1
rt = sp - (ct - 1) * r
sp = (rt - 1) * c + ct
end
if i \= sp then say 'swap('i',' sp')' /* swap elements */
end
end
Это распечатает элементы массива, которые нужно поменять местами. Это будет работать для матрицы любого размера, представленной в линейном массиве, где элементы располагаются по столбцу, а затем по строке. Используя N X 2 martix, элементы будут расположены следующим образом:
x 1,1 , x 1,2 , x 2,1 , x 2,2 , ... х н, 1 , х н, 2
Алгоритм распечатывает элементы, которые нужно поменять местами, чтобы получить массив в следующем порядке:
x 1,1 , x 2,1 , ... x n, 1 , x 1,2 , x 2,2 , ... x n, 2
Например, начать с r = 4, c = 2 и массива:
A1, B1, A2, B2, A3, B3, A4, B4
Требуются следующие свопы:
swap(2, 3)
swap(3, 5)
swap(4, 7)
swap(6, 7)
стать:
A1, A2, A3, A4, B1, B2, B3, B4
Этот алгоритм эффективен как в пространстве, так и во времени.
Big-O
Мой О-фу не велик, но я попробую ...
Матрица содержит 2 столбца («A» и «B») и «M» строк. Чтобы представить это как
линейный массив нам нужно 2М элементов. Позволяет назвать это число N (размер линейного массива).
Алгоритм имеет два цикла итерации, один для 'r' (строки) и один для 'c' (столбцы).
Тогда общее число итераций равно r * c, которое в нашем случае сводится к 2M = N. Пока все хорошо.
Подстановочный знак - внутренний цикл DO WHILE
. Сколько итераций требуется для данного числа строк?
Ответ может быть: довольно много.
На основании некоторых эмпирических результатов (показанных ниже) это выглядит как число DO WHILE
итераций
это сложная функция, включающая 'r', когда 'c' = 2 (или, возможно, любое значение 'c').
Мне не хватает O-foo, чтобы точно понять, что это за функция.
Тем не менее, он не должен быть хуже, чем N 3 (одна полная «погоня» через матрицу, N 2 , раз
каждый элемент, N). Не очень хорошая картина - в теории. Итак, я думаю, что это делает O (N 3 )? Это может быть
алгоритм не O (N), но с практической точки зрения, кажется, работает близко к O (N), учитывая биты
Эмпирические данные приведены ниже. Я немного растерялся - комментарии приветствуются!
Одно замечание о цикле DO WHILE
: используется целочисленная математика для простых переменных (без массива
ссылки обязательны). Если вы идете нелинейно, это имеет
быть «самым дешевым» местом для этого!
Сколько свопов требуется? Количество свопов ограничено одним на итерацию через внешний
две петли, что не более N раз. Количество свопов соответствует производительности O (N).
Я предполагаю, что это не O (N) алгоритм, но, похоже, он ведет себя разумно
для 2-х колоночных матриц среднего размера.
Вот некоторые эмпирические результаты для различных размеров матрицы из двух столбцов:
Rows Loops per row
========== =============
500 9
1,000 19
1,500 21
2,000 12
2,500 18
3,000 23
3,500 26
1,000,000 30
2,000,000 40
3,000,000 45
10,000,000 59
20,000,000 39
30,000,000 60
Число циклов в ряду растет с количеством строк, но не с пугающей скоростью. Опасность заключается в том, чтобы попасть в какое-то «сладкое» место, где оно становится экспоненциальным, но я не знаю, действительно ли у него такой потенциал.
Я бы посоветовал Mgccl сравнить этот алгоритм с диапазоном количества строк, которыеКак правило, в своем приложении он решает, будет ли он приемлемым по сравнению с другими тестами алгоритма.Анализ Big-O интересен, но вот результаты по рабочему диапазону данных.
Последний удар по банке: Почему этот алгоритм работает?
Транспонированиематрица, представленная в линейной форме:
Данная матрица X имеет M строк и N столбцов.
Разложите X в линейный массив в главном порядке строк.Массив будет организован следующим образом:
11, 12, 13, ... 1N, 21, 22, 23, ... 2N, ... M1, M2, M3 ... MN
Обозначение, описывающее каждый элемент в линейном массиве:
X[i,r,c]
where: i is the linear array index for element X
r is the row number for element X
c is the column number for element X.
Используя эту нотацию, можно создать массив в главном порядке строккак:
i = 0
for j = 1 to M /* Row counter */
for k = 1 to N /* Column counter */
i = i + 1 /* array index of element j, k */
say 'X['i','j',k']'
end
end
Обратите внимание, что при заданных значениях j (строка) и k (столбец) i можно рассчитать как:
i = (j - 1) * N + k
Транспонирование матрицы X строится путем обменаэлементы X [i, r, c] с X [t, c, r] в диапазоне r и c.По сути, мы обмениваем все переменные строки на переменные столбца.Используя обозначения, описанные выше, это равносильно замене элементов линейного массива:
exchange(X[i,r,c], X[t,c,r])
where: i = (r - 1) * N + c
t = (c - 1) * M + i
Количество обменов, необходимых для транспонирования матрицы, будет меньше, чем M * N, потому что для размещенияэлемент в правильном положении.В некоторых случаях обмен не потребуется, поскольку элемент уже «на месте».Например, первый и последний элементы X никогда не нуждаются в обмене.
Проходя через линейный массив с увеличением i, мы знаем, что пока ни один из обменов не включает элементы, где i> t, матрица будетв главном порядке столбцов для всех элементов, имеющих индексы, меньшие или равные i.
Всякий раз, когда i> t, это означает, что предшествующий обмен имел место в индексе t.Элемент в точке t был заменен, как указано выше, поместив его в новую позицию t '.Учитывая индекс t, мы можем вычислить главный индекс строки t ', а также номера строк и столбцов, связанные с ним, следующим образом:
c' = (t - 1) % M + 1
r' = t - (c' - 1) * M
t' = (r' - 1) * N + c'
Опять же, если t' меньше i, это означает, чтоэтот элемент также был обменен, и мы должны продолжить еще один раунд расчетов.Установите t в вычисленное значение t 'и повторите.В конце концов, я стану <= t, и обмен может быть сделан.По сути, мы «преследуем» элемент через все его предыдущие обмены, пока не найдем его в i или справа от i в линейном массиве. </p>
Повторите этот цикл для каждого элемента в линейном массиве, и матрица будетбыли транспонированы.