2015-01-21 1 views
3

У меня есть вектор, который, какциркулярно сдвиг вектора

x = [20 11 12 13 14 15 16 17 18 19] 

Я хотел бы сместить вектор значения, как указано

if (i = 1) 
X = [11 12 13 14 15 16 17 18 19 20] 

if (i = 2) 
X = [12 13 14 15 16 17 18 19 20 11] 

if (i = 3) 
X = [13 14 15 16 17 18 19 20 11 12] 

В настоящее время я использую for цикл, чтобы сделать это, но требуется много времени

x = [20 11 12 13 14 15 16 17 18 19]; 
in = x; 
C1 = x; 

for lt = 1:1:length(in) 
    C1 = x ; 

    if (lt > 1) 
     for tt = 1:1:lt-1 
      swap = C1(1); 

      for pt = 1:1:length(in)-1 
       C1(pt) = C1(pt+1);  
      end 

      C1(length(in)) = swap; 
     end 
    end  

    disp(C1); 
end 

Возможно, кто-нибудь предложит мне более быстрый алгоритм?

ответ

5

Позвольте s обозначить количество позиций, которые вы хотите сместить. Вы можете использовать circshift:

x_shifted = circshift(x, [1 -s]); 

Второй аргумент [1 -s], потому что вы хотите сдвинуть s позиции к оставил в второй размерности (столбцы).

Вы также можете сделать это вручную с mod:

x_shifted = x(mod((1:numel(x))+s-1, numel(x))+1); 
+0

Ну, я думаю, что я просто сделал версию '' bsxfun' вашего решения 'mod' ... надеюсь, что все в порядке! – Divakar

+0

@ Дивакар. Конечно! +1 уже –

4

circshift это путь, но вы также можете сделать это с довольно простой индексации:

x_shifted = x([(i+1):end , 1:(i-1)]) 

Это, однако, предполагает, что 1 < i && i < length(x).

+0

Проще чем использовать 'mod' –

+1

@ LuisMendo, но ограничивает область' i' ... – Dan

2

Вы можете предварительно вычислить все C1 в одном порядке (в векторе) до начала цикла (ов) и использовать их значения внутри цикла (ов) непосредственно с индексацией в одиночку и тем самым сэкономить время при их вычислении -

N = numel(x); 
C1_all = x(mod(bsxfun(@plus,[0:N-1]',0:N-1),N)+1) 

код для запуска данного x -

C1_all = 
    20 11 12 13 14 15 16 17 18 19 
    11 12 13 14 15 16 17 18 19 20 
    12 13 14 15 16 17 18 19 20 11 
    13 14 15 16 17 18 19 20 11 12 
    14 15 16 17 18 19 20 11 12 13 
    15 16 17 18 19 20 11 12 13 14 
    16 17 18 19 20 11 12 13 14 15 
    17 18 19 20 11 12 13 14 15 16 
    18 19 20 11 12 13 14 15 16 17 
    19 20 11 12 13 14 15 16 17 18 
+0

Хорошее решение. Я подумал, что интересно, что внутри 'hankel' ([как решение Rayryeng] (http://stackoverflow.com/a/28073572/2778484)), он делает именно то, что вы сделали. – chappjc

+0

@chappjc Интересно узнать это! Не так много из «hankel' person, хотя;) Спасибо, что поделились им. – Divakar

1

Я также могу предложить использовать hankel. Вы можете использовать hankel, чтобы сгенерировать набор индексов, которые вы использовали бы для индексации в x, где каждая строка дает вам сумму кругового сдвига, которую вы ищете. Что-то вроде этого:

x = [20 11:19]; 
c = x(hankel([1:numel(x)], [numel(x) 1:numel(x)-1])) 

c = 

    20 11 12 13 14 15 16 17 18 19 
    11 12 13 14 15 16 17 18 19 20 
    12 13 14 15 16 17 18 19 20 11 
    13 14 15 16 17 18 19 20 11 12 
    14 15 16 17 18 19 20 11 12 13 
    15 16 17 18 19 20 11 12 13 14 
    16 17 18 19 20 11 12 13 14 15 
    17 18 19 20 11 12 13 14 15 16 
    18 19 20 11 12 13 14 15 16 17 
    19 20 11 12 13 14 15 16 17 18 
+0

Гораздо чище, чем решение 'bsxfun', но интересно,' hankel' использует 'bsxfun (@plus, ...)' внутренне как Divakar, но без суеты сложного синтаксиса. Должен сказать, что для новичков это сложно. :) +1 и вам, и Дивакару. – chappjc

+0

@chappjc - Да! Что ты знаешь. Я никогда не пользовался возможностью посмотреть на источник. Определенно хорошо знать. Благодаря :) – rayryeng