三次逆序实现数组的循环移位

很久前在《编程珠玑》上看到的经典算法,今天看到一道相关的笔试题,于是又想了起来,顺手记录一下。

比如有数组元素1 2 3 4 5 6,要循环右移3位变成4 5 6 1 2 3.循环移位算法逻辑很简单,普通方法也能很快想出并立即实现,但问题在于多次大范围移动数组元素,在数组元素较多时整体效率较低;而本文的算法则不存在这种问题。

通过逆序方法实现移位,首先将数组元素分成两组。要右移3次,于是将右侧3个元素作为一组,左侧剩下的3个为一组。为示例方便,以下用逗号将数组分隔成两个组,即:

1 2 3,4 5 6

第一次对左侧这组逆序,完成后数组元素排列如下:

3 2 1,4 5 6

第二次对右侧这组逆序,完成后数组元素排列如下:

3 2 1,6 5 4

最后一次,对整个数组逆序,完成后排列如下:

4 5 6 1 2 3

三次逆序就达到目的。循环左移情况类似。

下面给出我对上述例子的简单实现:

#include<stdio.h>
#include<assert.h>

void reverse(int array[],int start,int end)
{
    assert(start>-1&&end>-1);
    int temp;
    while(start<end)
    {
        temp=array[end];
        array[end--]=array[start];
        array[start++]=temp;
    }
}

void right_shift(int array[],int count,int shift)
{
    int sep=count-shift;
    int end=count-1;
    reverse(array,0,sep-1);
    reverse(array,sep,end);
    reverse(array,0,end);
}

int main()
{
    int array[]={1,2,3,4,5,6};
    for(int i=0;i<6;++i)
    {
        printf("%d ",array[i]);
    }
    printf("\n");
    right_shift(array,6,3);
    for(int i=0;i<6;++i)
    {
        printf("%d ",array[i]);
    }
    printf("\n");
    return 0;
}

right_shift

这种算法的思想很多地方可以借鉴。又有一道笔试题,要求将一句话里的单词倒置,标点符号不倒置。如“I am a student.”倒置后就是“student. a am I”,实现起来也很容易,以空格为界限,将字符串分成三组,然后对三组字符串分别逆序,最后对整个字符串进行逆序,这样就完成了整句话中单词的倒置。 

你可能感兴趣的:(循环,移位,逆序)