Сообщение Re: Транспонируем матрицу in place от 29.12.2016 15:25
Изменено 29.12.2016 15:54 kov_serg
Здравствуйте, nikov, Вы писали:
N>Дана прямоугольная матрица из целых чисел размера M×N, расположенная в памяти построчно в виде непрерывного линейного массива. Написать программу, которая транспонирует эту матрицу in place, используя дополнительную память не более O(max(M,N)).
В чем собственно трудность?
Если поменять функцию доступа к элементам то вообще никакой работы не надо производить
Вариант без затрат по памяти
N>Бонус: написать программу, которая поворачивает блок целых чисел размера M×N×K in place вокруг псевдо-диагонали, состоящей из элементов с индексами (0,0,0), (1,1,1), (2,2,2), ..., чтобы получился блок K×M×N, используя дополнительную память не более O(max(M,N,K)).
Меняем функцию доступа
Со сдвигом индексов примерно так же как и с транспонированием, только длиннее.
N>Можно ли улучшить эти алгоритмы, чтобы использовать дополнительную память не более O(log(max(M,N))) и O(log(max(M,N,K))), соответственно?
До, но работать будут медленнее.
N>Дана прямоугольная матрица из целых чисел размера M×N, расположенная в памяти построчно в виде непрерывного линейного массива. Написать программу, которая транспонирует эту матрицу in place, используя дополнительную память не более O(max(M,N)).
В чем собственно трудность?
Если поменять функцию доступа к элементам то вообще никакой работы не надо производить
get(i,j)=mtx(i*M+j)
get_tr=get(j,i)
Вариант без затрат по памяти
#include <stdio.h>
int step(int i,int m,int n) { return (i%n)*m+(i/n); }
int need(int i,int m,int n) {
int j,k;
for(j=1;j<i-1;j++) {
k=j;
do {
k=step(k,m,n);
if (i==k) return 0;
} while(k!=j);
}
return 1;
}
void tr(int *x,int m,int n) {
int i,j,k,w,v,mn=m*n;
for(i=1;i<mn;i++) {
if (!need(i,m,n)) continue;
j=step(k=i,m,n); w=x[k];
while(i!=j) {
v=w; w=x[j]; x[j]=v;
k=j; j=step(k,m,n);
}
x[i]=w;
}
}
void show(int *x,int m,int n,int dm,int dn) {
int i,j;
for(i=0;i<m;i++) {
for(j=0;j<n;j++) {
printf("%3d",x[i*dm+j*dn]);
}
printf("\n");
}
}
int main(int argc,char** argv) {
enum { M=3, N=7 };
int i,x[M*N];
for(i=0;i<M*N;i++) x[i]=i;
show(x,M,N,N,1);printf("\n");
show(x,N,M,1,N);printf("\n");
tr(x,M,N);
show(x,N,M,M,1);printf("\n");
return 0;
}
N>Бонус: написать программу, которая поворачивает блок целых чисел размера M×N×K in place вокруг псевдо-диагонали, состоящей из элементов с индексами (0,0,0), (1,1,1), (2,2,2), ..., чтобы получился блок K×M×N, используя дополнительную память не более O(max(M,N,K)).
Меняем функцию доступа
get_rot(i,j,k)=get(k,i,j)
Со сдвигом индексов примерно так же как и с транспонированием, только длиннее.
N>Можно ли улучшить эти алгоритмы, чтобы использовать дополнительную память не более O(log(max(M,N))) и O(log(max(M,N,K))), соответственно?
До, но работать будут медленнее.
Re: Транспонируем матрицу in place
Здравствуйте, nikov, Вы писали:
N>Дана прямоугольная матрица из целых чисел размера M×N, расположенная в памяти построчно в виде непрерывного линейного массива. Написать программу, которая транспонирует эту матрицу in place, используя дополнительную память не более O(max(M,N)).
В чем собственно трудность?
Если поменять функцию доступа к элементам то вообще никакой работы не надо производить
Вариант без затрат по памяти
N>Бонус: написать программу, которая поворачивает блок целых чисел размера M×N×K in place вокруг псевдо-диагонали, состоящей из элементов с индексами (0,0,0), (1,1,1), (2,2,2), ..., чтобы получился блок K×M×N, используя дополнительную память не более O(max(M,N,K)).
Меняем функцию доступа
Со сдвигом индексов примерно так же как и с транспонированием, только длиннее.
N>Можно ли улучшить эти алгоритмы, чтобы использовать дополнительную память не более O(log(max(M,N))) и O(log(max(M,N,K))), соответственно?
До, но работать будут медленнее.
N>Дана прямоугольная матрица из целых чисел размера M×N, расположенная в памяти построчно в виде непрерывного линейного массива. Написать программу, которая транспонирует эту матрицу in place, используя дополнительную память не более O(max(M,N)).
В чем собственно трудность?
Если поменять функцию доступа к элементам то вообще никакой работы не надо производить
get(i,j)=mtx(i*M+j)
get_tr=get(j,i)
Вариант без затрат по памяти
#include <stdio.h>
int step(int i,int m,int n) { return (i%n)*m+(i/n); }
int need(int i,int m,int n) {
int k=i;
do {
k=step(k,m,n);
if (k<i) return 0;
} while(k!=i);
return 1;
}
void tr(int *x,int m,int n) {
int i,j,k,w,v,mn=m*n;
for(i=1;i<mn;i++) {
if (!need(i,m,n)) continue;
j=step(k=i,m,n); w=x[k];
while(i!=j) {
v=w; w=x[j]; x[j]=v;
j=step(k=j,m,n);
}
x[i]=w;
}
}
void show(int *x,int m,int n,int dm,int dn) {
int i,j;
for(i=0;i<m;i++) {
for(j=0;j<n;j++) {
printf("%3d",x[i*dm+j*dn]);
}
printf("\n");
}
}
int main(int argc,char** argv) {
enum { M=3, N=7 };
int i,x[M*N];
for(i=0;i<M*N;i++) x[i]=i;
show(x,M,N,N,1);printf("\n");
show(x,N,M,1,N);printf("\n");
tr(x,M,N);
show(x,N,M,M,1);printf("\n");
return 0;
}
N>Бонус: написать программу, которая поворачивает блок целых чисел размера M×N×K in place вокруг псевдо-диагонали, состоящей из элементов с индексами (0,0,0), (1,1,1), (2,2,2), ..., чтобы получился блок K×M×N, используя дополнительную память не более O(max(M,N,K)).
Меняем функцию доступа
get_rot(i,j,k)=get(k,i,j)
Со сдвигом индексов примерно так же как и с транспонированием, только длиннее.
N>Можно ли улучшить эти алгоритмы, чтобы использовать дополнительную память не более O(log(max(M,N))) и O(log(max(M,N,K))), соответственно?
До, но работать будут медленнее.