Przesuwanie elementow

0

Czesc, prosze o pomoc bo sam nie moge znalezc gdzie tkwi problem.

Mamy n elementowa tablice, naszym zadaniem jest przesunac wybrane elementy tablicy o k elementow. Gdy k<0 to przesuwamy elementy w lewo. Niech b bedzie poczatkowym elementem do przesuniecia a e koncowym oraz k informuje o ile przesuwamy.

Problem pojawia sie gdy interesujacy nas obszar wykracza po za zakres czyli mamy elementy: data[n-1] data[n] data[0] data[1] data[2].
W pozostalych przypadkach moj kod jest poprawny.

Sytuacja gdy k < 0 i przesuwamy w lewo:

   if (b>e){
                schowek = e;
                e = b;
                b = schowek;
            }
            k = k * -1;
            if (b+k>n-1 || e+k>n-1) {
             dlugoscFragmentu = n - b + e + 1;
             iloscRozkazow = k / dlugoscFragmentu;
             iloscRozkazow = iloscRozkazow * dlugoscFragmentu;
             iloscRozkazow = k - iloscRozkazow;
             for (int i=0; i<iloscRozkazow; i++){
                schowek = data[b];
                for (int j=b;j<=e-1;j++) data[j] = data[j+1];
                data[e] = schowek;
                }
            }

Sytuacja gdy k >=0 i przesuwamy w prawo:

   if (b+k>n-1 || e+k>n-1) {
                dlugoscFragmentu = n - b + e + 1;
                iloscRozkazow = k / dlugoscFragmentu;
                iloscRozkazow = iloscRozkazow * dlugoscFragmentu;
                iloscRozkazow = k - iloscRozkazow;
                for (int i=0;i<iloscRozkazow;i++){
                    schowek = data[e];
                    for (int j=e-1;j>=b;j--) data[j+1] = data[j];
                    data[b] = schowek;
                } 
0

Przepraszam, że nie analizuję twojego kodu. Nie cierpię analizy kodów. :/

Uwaga: indeksy liczę od 0 - tak, jak w C++.

Nie uwzględniam następujących przypadków, trzeba je obsłużyć jeszcze przed przesunięciem:

  1. |k| > n (przesunięcie większe niż rozmiar tablicy);
  2. b > e lub b < 0 lub e < 0 (niepoprawnie zdefiniowany podciąg);
  3. b > n lub e > n (podciąg poza zakresem tablicy);

1. Na początek:

Na przesunięcie bez zawijania mamy b "dostępnych" elementów w lewo oraz (n - 1) - e "dostępnych" elementów w prawo.

2. Jeśli jednak przekroczymy ten zakres, to mamy dwa przypadki do rozpatrzenia:

a) Przypadek k < 0:

Jeśli k < 0 oraz -k > b (czyli wchodzimy na elementy "ujemne", przekraczające zakres tablicy "w dół", jak ja to mówię), to musimy nasz podciąg (o długości e - b + 1) zawinąć o k + b elementów, to znaczy - tyle elementów naszego podciągu będzie "z tyłu" tablicy.

Jeżeli jednak k >= 0 oraz -k > e (czyli "w tył" trzeba zawinąć nawet ostatni element podciągu), to należy po prostu przesunąć podciąg w prawo o (n - (-k - e)) - e == n + k elementów.

b) Przypadek k >= 0:

Jeśli k >= 0 oraz k > (n - 1) - e (czyli wchodzimy na elementy przekraczające zakres tablicy "w górę"), to musimy nasz podciąg zawinąć o k - ((n - 1) - e) elementów, to znaczy - tyle elementów naszego podciągu będzie "z przodu" tablicy.

Jeżeli jednak k >= 0 oraz k > (n - 1) - b (czyli "w przód" trzeba zawinąć nawet pierwszy element podciągu), to należy po prostu przesunąć podciąg w lewo o (b + 1) - (k - ((n - 1) - b)) == n - k elementów.

Jeśli jest tu błąd, pisz. Najbardziej mogły mi umknąć jedynki (+/- 1), związane z tym, że indeksy liczę od 0.

1

Myślę, że można to zrobić prościej, gdyż albowiem ustalenie nowej pozycji to w rzeczywistości operacja modulo:

n=5
k=2
[b,e]=(2,3,4)

Wtedy nowa pozycja dla x to x+k mod n
2+2 mod 5 = 4 mod 5 = 4
3+2 mod 5 = 5 mod 5 = 0
4+2 mod 5 = 6 mod 5 = 1

W C/C++ skorzystać musisz oczywiście z operatora reszty z dzielenia %. Jednak UWAGA, bo reszta z dzielenia dla wartości ujemnych zachowuje się inaczej niż modulo:

n=5
k=-3
2-3 mod 5 = -1 mod 5 = 4
2-3 % 5 = -1 % 5 = -1

Ale można to obejść dodając jeszcze n i stworzyć w ten sposób uniwersalny algorytm:

y=(x+k+n) % n
dla poprzednich przypadków:
2+2+5 % 5 = 9 % 5 = 4
3+2+5 % 5 = 10 % 5 = 0
4+2+5 % 5 = 11 % 5 = 1
2-3+5 % 5 = 4 % 5 = 4

1 użytkowników online, w tym zalogowanych: 0, gości: 1