Optimal way to perform a shift operation on an array

前端 未结 6 1497
醉酒成梦
醉酒成梦 2021-02-20 08:00

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

相关标签:
6条回答
  • 2021-02-20 08:18

    I wonder if perhaps you should be using a std::valarray.

    0 讨论(0)
  • 2021-02-20 08:33

    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;
    }
    
    0 讨论(0)
  • 2021-02-20 08:35

    If you really want BLAZING speed look at the assembler shift with carry operations. http://en.wikibooks.org/wiki/X86_Assembly/Shift_and_Rotate#Shift_With_Carry_Instructions Coupled with a loop you can bitshift an array in milliseconds.

    0 讨论(0)
  • 2021-02-20 08:40

    If you're the only person with a pointer to the array, just increment the pointer and decrement the length.

    Just remember to keep the original pointer around for when you free it.

    0 讨论(0)
  • 2021-02-20 08:42

    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.

    0 讨论(0)
  • 2021-02-20 08:42

    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).

    0 讨论(0)
提交回复
热议问题