* Пример за циклично преместване на k позиции елементите на масив
m
от n елемента.
n = 6, k = 2 0 1 2 3 4 5 ->
2 3 4 5 0 1
* Алгоритъм 1:
- копираме първите k елемента на m в друг масив x;
- преместваме n-k елемента на m на k позиции вляво;
- копираме елементите на x обратно в m на последните
k
позиции.
Сложност O(n), допълнителна памет k елемента.
* Алгоритъм 2:
Описания алгоритъм за k = 1. За да осъществим циклично преместване
с k елемента, е необходимо да приложим този алгоритъм k
пъти.
Сложност O(n2), допълнителна памет
1 елемент.
* Алгоритъм 3:
- копираме m[0] в x;
- преместваме m[k] в m[0], преместваме
m[2k%n]
в m[k], преместваме m[3k%n] в m[2k%n]
и
т.н. докато стигнем последния непреместен елемент, който го заменяме с
x
(Пример А). Ако достигнем до преместен елемент, спираме и започваме отначало
по същия начин, като заменяме k с
k+1 (Пример
Б).
Пример А n = 11, k = 3:
0 1 2 3 4 5 6 7 8 9 10 -> 3 4 5 6 7 8 9 10 0 1 2 m: 0 1 2 3 4 5 6 7 8 9 10 | x: m: 0 1 2 3 4 5 6 7 8 9 10 | x: 0 m: 3 1 2 3 4 5 6 7 8 9 10 | x: 0; m: 3 1 2 6 4 5 6 7 8 9 10 | x: 0; m: 3 1 2 6 4 5 9 7 8 9 10 | x: 0; m: 3 1 2 6 4 5 9 7 8 1 10 | x: 0; m: 3 4 2 6 4 5 9 7 8 1 10 | x: 0; m: 3 4 2 6 7 5 9 7 8 1 10 | x: 0; m: 3 4 2 6 7 5 9 10 8 1 10 | x: 0; m: 3 4 2 6 7 5 9 10 8 1 2 | x: 0; m: 3 4 5 6 7 5 9 10 8 1 2 | x: 0; m: 3 4 5 6 7 8 9 10 8 1 2 | x: 0; m: 3 4 5 6 7 8 9 10 0 1 2 | x: 0; |
Пример Б n = 9, k = 3:
0 1 2 3 4 5 6 7 8 -> 3 4 5 6 7 8 0 1 2 m: 0 1 2 3 4 5 6 7 8 | x: m: 3 1 2 3 4 5 6 7 8 | x: 0; m: 3 1 2 6 4 5 6 7 8 | x: 0; m: 3 1 2 6 4 5 0 7 8 | x: 0; m: 3 1 2 6 4 5 0 7 8 | x: 1; m: 3 4 2 6 4 5 0 7 8 | x: 1; m: 3 4 2 6 7 5 0 7 8 | x: 1; m: 3 4 2 6 7 5 0 1 8 | x: 1; m: 3 4 2 6 7 5 0 1 8 | x: 2; m: 3 4 5 6 7 5 0 1 8 | x: 2; m: 3 4 5 6 7 8 0 1 8 | x: 2; m: 3 4 5 6 7 8 0 1 2 | x: 2; |
Сложност O(n), допълнителна памет 1 елемент.
* Алгоритъм 4 (разделяй и владей):
- разделяме масива на 2 части: A - първите k елемента и B -
последните n-k елемента;
- разделяме масива B на 2 части, Br - последните k елемента,
Bl - останалите елементи;
- разменяме местата на елементите на A и Br;
- прилагаме същия алгоритъм за масива B.
Пример.
n = 11, k = 3:
0 1 2 3 4 5 6 7 8 9 10 -> 3 4 5 6 7 8 9
10 0 1 2
[0 1 2 3 4 5 6 7 8 9 10]
A = [0 1 2], Bl = [3 4 5 6 7], Br = [8 9 10]
[8 9 10 3 4 5 6 7 0 1 2 ]
[8 9 10 3 4 5 6 7 ] [0 1 2]
A = [8 9 10], Bl =[3 4], Br = [5 6 7]
[5 6 7 3 4 8 9 10]
[5 6 7 3 4] [8 9 10 0 1 2]
A = [5 6 7], Bl = [], Br = [3 4 5]
[ 3 4 5 6 7]
[3 4 5 6 7 8 9 10 0 1 2]
Сложност O(n), допълнителна памет - константа.
* Алгоритъм 5 (Кърниган и Плоджер):
Пример.
n = 11, k = 3:
0 1 2 3 4 5 6 7 8 9 10 -> 3 4 5 6 7 8 9 10 0 1 2
A = [0 1 2], B = [3 4 5 6 7 8 9 10], AB = [0 1
2 3 4 5 6 7 8 9 10]
AR = [2 1 0], BR = [10 9
8 7 6 5 4 3], AR BR = [2 1 0 10 9 8
7 6 5 4 3]
(AR BR)R = [3 4 5 6
7 8 9 10 0 1 2]
// shift3.c
#include <stdio.h>
#define N 11
int m[N];
void reverse(unsigned a, unsigned b)
{ unsigned i, j, k, c;
int tmp;
for (c=(b-a)/2, k=a, j=b, i=0;
i<c; i++, j--, k++)
{ tmp = m[k];
m[k] = m[j];
m[j] = tmp;
}
}
void shift3(unsigned k)
{ reverse(0, k-1);
reverse(k, N-1);
reverse(0, N-1);
}
int main()
{
int i;
for (i=0; i<N; i++) m[i]=i;
shift3(3);
for (i=0; i<N; i++) printf("%d
", m[i]);
printf("\n");
return 0;
}
Сложност O(n), допълнителна памет - константа.