数组移动算法

来源:互联网 发布:士爵刷枪软件安卓版 编辑:程序博客网 时间:2024/05/16 20:14

对于有n个元素的数组 int a[n]={....};写一个高效算法将数组内容循环左移m位
比如: int a[6] ={1,2,3,4,5,6} ,循环左移3位得到结果{456123},
要求:
1不允许另外申请数组空间,但可以申请少许变量
2不允许采用每次左移

//////////////////////////////////////////////
算法的基本思想如下:
设有一个包含8个数的数组 int a[8] = {1, 2, 3, 4, 5, 6, 7, 8}; 将其内容循环左移3位,即左移后的
结果是4, 5, 6, 7, 8, 1, 2, 3。
    从上例可以看出,将1,2,3移到了数组的最后,从4开始,直到8都往前移动了3个位置。因此我们可设想
将1,2,3看成一个整体先和4, 5, 6交换, 再和7, 8交换。
    第一次交换的结果:
    4, 5, 6, 1, 2, 3, 7, 8
    由于7,8只有两位,因此第二次交换只和1,2,3中的1,2进行交换。结果如下:
    4, 5, 6, 7, 8, 3, 1, 2。
    可以看出,前五位已经满足了最终结果,只有后3位还不满足最终结果。但是只要将3, 1, 2看成一个
子数组,再将这个子数组循环左移1位,即可变成1, 2, 3。

    因此在移动元素时可将要左移的m位看成一个整体(如上例中的1, 2, 3),依次和它后面的相同位数的
数组元素交换,如果后面的元素不足m位,假设为t位,t < m,那么只交换t位,这样,前面的数组元素(前n - m个元素一定满足条件)。
最后将后面m个元素看成一个子数组,再对其进行循环左移m - n % m位。

算法的时间复杂度为O(n),空间复杂度为O(1)。

c实现如下(move_array为算法实现函数,并带有测试用例):

#include <stdio.h>
void swap(int *a, int *b)
{
    int x;
    x = *a;
    *a = *b;
    *b = x;
}
//这个函数为算法实现部分
/////////////////////////////////////////
void move_array(int data[], int n, int m)
{
    int i, j;
    m = m % n;
    if(m == 0) return;
    for(i = 0; i < n - m; i += m)
    {
        for(j = i; j < i + m && j < n - m; j++)
        {
            swap(&data[j], &data[j + m]);
        }
    }
    move_array(data + n - m, m, m - n % m);
}
/////////////////////////////////////////
int main()
{
    int data1[] = {1, 2, 3, 4, 5, 6, 7, 8};
    int data2[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14};
    int data3[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
    int data4[] = {1, 2, 3, 4, 5, 6};
    int data5[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18};
    int i;
    move_array(data1, 8, 5);
    for(i = 0; i < 8; i++)
        printf("%d ", data1[i]);
    printf("/n");

    move_array(data2, 14, 18);
    for(i = 0; i < 14; i++)
        printf("%d ", data2[i]);
    printf("/n");

    move_array(data3, 9, 3);
    for(i = 0; i < 9; i++)
        printf("%d ", data3[i]);
    printf("/n");

    move_array(data4, 6, 3);
    for(i = 0; i < 6; i++)
        printf("%d ", data4[i]);
    printf("/n");

    move_array(data5, 18, 17);
    for(i = 0; i < 18; i++)
        printf("%d ", data5[i]);
    printf("/n");

    return 0;
}