Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Optimal way to perform a shift operation on an array

Tags:

c++

c

Suppose I have an array

unsigned char arr[]= {0,1,2,3,4,5,6,7,8,9};

Is there a way to perform shift operation on them besides just copying them all into another array. We can easily do it using linked lists but I was wondering if we can use a shift operator and get work done faster.

Note: The data in this question is just an example. The answer should be irrecpective of the data in the array.

like image 690
tomkaith13 Avatar asked Dec 14 '09 20:12

tomkaith13


People also ask

Which algorithm is best for array rotation?

The block swap algorithm for array rotation is an efficient algorithm that is used for array rotation. It can do your work in O(n) time complexity. So, in array rotation, we are given an array arr[] of size n and a number k that define the no.

How do you shift right to an array?

An array is said to be right rotated if all elements of the array are moved to its right by one position. One approach is to loop through the array by shifting each element of the array to its next position. The last element of the array will become the first element of the rotated array.

What does the array shift () method do and what does it return?

The shift() method removes the first element from an array and returns that removed element.


3 Answers

If you're looking for a pure C solution, here it is, including a driver program. It turns out to be pretty simple: to rotate by n, you:

  1. reverse the first n elements in-place,
  2. reverse the remaining elements in-place, and
  3. reverse the whole array in-place.

This requires one element worth of extra storage (for reversing).

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>

/* print an array */
static void print_array(unsigned char *arr, size_t n, const char *prefix)
{
    size_t i;

    if (prefix) {
        printf("%s: ", prefix);
    }
    for (i=0; i < n; ++i) {
        printf("%02x ", (unsigned int)arr[i]);
    }
    printf("\n");
}

/* reverse 'arr', which has 'narr' elements */
static void reverse(unsigned char *arr, size_t narr)
{
    size_t i;

    for (i=0; i < narr / 2; ++i) {
        unsigned char tmp = arr[i];
        arr[i] = arr[narr-i-1];
        arr[narr-i-1] = tmp;
    }
}

/* rotate 'arr' of size 'narr' by 'shift' */
static void rotate(unsigned char *arr, size_t narr, unsigned long shift)
{
    reverse(arr, shift);
    reverse(arr + shift, narr - shift);
    reverse(arr, narr);
}

/* driver program */
int main(int argc, char *argv[])
{
    unsigned char arr[]= {0,1,2,3,4,5,6,7,8,9,10};
    size_t narr = sizeof arr / sizeof arr[0];
    unsigned long shift = 2;

    if (argc > 1) {
        char *eptr;
        shift = strtoul(argv[1], &eptr, 0);
        if (*eptr || errno == ERANGE) {
            perror("strtoul");
            return EXIT_FAILURE;
        }
    }
    print_array(arr, narr, "before shift");
    rotate(arr, narr, shift);
    print_array(arr, narr, "after shift");
    return EXIT_SUCCESS;
}
like image 60
Alok Singhal Avatar answered Nov 03 '22 00:11

Alok Singhal


If you want a circular shift of the elements:

std::rotate(&arr[0], &arr[1], &arr[10]);

... will do the trick. You'll need to #include the algorithm header.

like image 38
maxaposteriori Avatar answered Nov 03 '22 00:11

maxaposteriori


As long as the array is modifiable, you can use memmove to shift them (but don't mistakenly use memcpy as memcpy is not meant for overlapping regions):

memmove(&arr[0], &arr[1], sizeof(arr) - sizeof(*arr));

(sizeof(arr) - sizeof(*arr) is the size in bytes of all but 1 element of the array).

like image 23
R Samuel Klatchko Avatar answered Nov 02 '22 23:11

R Samuel Klatchko