Cyclic array shift

For example, you need to perform a cyclic shift to the right by n elements. And how to make a cyclic shift to the right by -n elements? What will the array look like?

Just write what the correct answer is: Array - 1 2 3 4 5 Shift to the right by -2 (negative number)

Is the answer 3 4 5 1 2 or 3 4 5 2 1 correct ?

Author: ordman, 2011-09-13

7 answers

The correct answer is 3 4 5 1 2

Update

A cyclic shift to the right by -2 is the same as a cyclic shift to the left by 2.

There is an amazing algorithm of three reverse(array, size) for cyclic shift to the left, which is easy to remember and in the implementation of which it is almost impossible to make a mistake.

Here's how it works with 12345 (s[] = 12345, size = 5, dist = 2)

reverse(s, dist);               // 21|345
reverse(s + dist, size - dist); // 21|543
reverse(s, size);               // 34512

They write that Ken Thompson wrote an editor with the reverse function in 1971, and he claims that it was already legendary back then.

PS
it so happened that I recently compared the performance of the algorithm with shift permutation of blocks (which on average requires less shipments of array elements I used before) and was surprised to find that the algorithm for reverse(), despite the larger number of memory operations, even a little faster.
So I decided to share it.

 10
Author: avp, 2016-07-13 22:43:49

In most languages, this is probably already implemented. For example, in C++, this is std::rotate from <algorithm>

std::rotate(&a[first], &a[middle], &a[last]);

After that, a cyclic shift occurs, so that the middle becomes the first element. Regarding the shift to the right, to the left: due to the cyclicity, a shift to the right by n elements is a shift to the left by m - n elements, where m is the size of the array.

If you need to write in C (a training task, I understand?), then you can take the same implementation from STL

ForwardIterator next = middle;
while (first != next)
{
    swap (*first++, *next++);
    if (next == last)
        next = middle;
    else if (first == middle) 
        middle = next;
}

Coarsening, the idea of the work is as follows (shift to the left by 1):

1234
2134
2314
2341
 8
Author: Nicolas Chabanovsky, 2011-09-13 12:47:42
    int[] a = new int[]{236, 267, 973, 357};
    int n = 1;
    int[] b = new int[a.length];
    for (int i = a.length-1; i >= 0; i--) {
        if(i+n >= a.length){
            b[i+n-a.length] = a[i];
        }
        else{
            b[i+n] = a[i];
        }
    }
    for (int i : b) {
        System.out.println(i);
    }

At the output in the console, you will get a right shift of n (by 1).

P.S. I am not sure that the construction of the first line exists in C, because I write in Java, but the basic idea should be clear. And the output of the result is also different)

 5
Author: Sasha121, 2011-09-13 08:14:56

I will give an example under C#. I don't know if it's clearer or not, I usually write like this. The method can be designed as an extension. If the shiftValue is positive, the shift is to the right, and if the shiftValue is negative, the shift is to the left.

public static T[] Shift<T>(T[] array, int shiftValue)
{       
    var newArray = new T[array.Length];
    shiftValue -= array.Length;
    if(shiftValue < 0)
    {
        shiftValue*=-1;
    }


    for(var i=0; i<array.Length; i++)
    {
        var index = (i + shiftValue) % array.Length;

        newArray[i] = array[index]; 
    }
    return newArray;
}
 4
Author: timon, 2016-01-10 16:19:58

I typed from the body, but it seems like this

Right

for (I = 1; I <= n; I++)
{ 
    b = [10];
    for (j = 10; j <= 0; j = j - 1)
        a[j]=[j-1];
    a[1] = b;
}

Left

for (j = 1; j <= n; j++) 
{
    int first = a[1];
    for (i = 1; i < 10; i++)
    a[i] = a[i + 1];
    a[10] = first;
}
 3
Author: Leshij_2005, 2011-09-13 08:18:28

That's how it works for me.

void array_Rotate_Right(unsigned char*p,unsigned char e){    
    unsigned char i,i1;    
    for (i1=0;i1<e;i1++){    
        for(i = 6; i>0; i--){    
            p[i]>>=1;    
            if((p[i-1]&0x1)==0x1) p[i]+=128;    
        }    
    p[0]>>=1;    
    }    
}
 -2
Author: Pro3, 2016-09-13 11:58:56

I don't know what language you wanted, I'll write it in C++, it will turn out something like this

for (int i = /*сюда число, какой длины массив*/; i >= 0; i--)
{
    a[i+n] = a[i];
}
 -5
Author: arman_pap, 2011-09-13 07:07:10