Cette approche est assez rapide :
X = randn(500,2000); %// example input matrix
[r, c] = size(X);
M = bsxfun(@plus, (1:r).', 0:c-1);
M = M + bsxfun(@times, (1:r).'/(r+c), (-1).^M);
[~, ind] = sort(M(:));
y = X(ind).'; %'// output row vector
Analyse comparative
Le code suivant compare le temps d'exécution avec celui de L'excellente réponse d'Amro en utilisant timeit
. Il teste différentes combinaisons de la taille de la matrice (nombre d'entrées) et de sa forme (rapport entre le nombre de lignes et le nombre de colonnes).
%// Amro's approach
function y = zigzag_Amro(M)
ind = reshape(1:numel(M), size(M));
ind = fliplr( spdiags( fliplr(ind) ) );
ind(:,1:2:end) = flipud( ind(:,1:2:end) );
ind(ind==0) = [];
y = M(ind);
%// Luis' approach
function y = zigzag_Luis(X)
[r, c] = size(X);
M = bsxfun(@plus, (1:r).', 0:c-1);
M = M + bsxfun(@times, (1:r).'/(r+c), (-1).^M);
[~, ind] = sort(M(:));
y = X(ind).';
%// Benchmarking code:
S = [10 30 100 300 1000 3000]; %// reference to generate matrix size
f = [1 1]; %// number of cols is S*f(1); number of rows is S*f(2)
%// f = [0.5 2]; %// plotted with '--'
%// f = [2 0.5]; %// plotted with ':'
t_Amro = NaN(size(S));
t_Luis = NaN(size(S));
for n = 1:numel(S)
X = rand(f(1)*S(n), f(2)*S(n));
f_Amro = @() zigzag_Amro(X);
f_Luis = @() zigzag_Luis(X);
t_Amro(n) = timeit(f_Amro);
t_Luis(n) = timeit(f_Luis);
end
loglog(S.^2*prod(f), t_Amro, '.b-');
hold on
loglog(S.^2*prod(f), t_Luis, '.r-');
xlabel('number of matrix entries')
ylabel('time')
La figure ci-dessous a été obtenue avec Matlab R2014b sur Windows 7 64 bits. Les résultats dans R2010b sont très similaires. On constate que la nouvelle approche réduit le temps d'exécution par un facteur compris entre 2,5 (pour les petites matrices) et 1,4 (pour les grandes matrices). Les résultats sont presque insensibles à la forme de la matrice, étant donné le nombre total d'entrées.
0 votes
Existe-t-il une formule générique pour l'indice (par exemple, 1,1 ->1, 1,2->2, 2,1 -> 3) etc. idx = f(i,j,m,n)>.
0 votes
+1, j'ai dû écrire moi-même le générique du zigzag comme devoir scolaire il y a 3 semaines. Je suis aussi curieux de savoir s'il est possible de faire ça sans boucles.