问题:将一个n元一维向量向左旋转i个位置,例如,当n=8且i=3时,向量abcdefgh旋转为defghabc。
解决办法:
1.求模置换
移动x[0]到临时变量i,然后移动x[i]至x[0],x[2i]至[i],依次类推,将x中的所有下标对n取模,直至返回到取x[0]中的元素,此时改为从t取值然后终止过程。
//求公约数
unsigned int Gcd(unsigned int a, unsigned int b)
{
unsigned int temp;
while (b != 0)
{
temp = a % b;
a = b;
b = temp;
}
return a;
}
// 求模置换函数
// array:置换数组
// nDataLen:数组长度
// nTranslation:平移位数
void modShift(int array[], int nDataLen, int nTranslation)
{
unsigned int gcd = Gcd(nDataLen, nTranslation);
for (int i = 0; i < gcd; i ++)
{
int temp = array[i];
int j = i;
int k;
while(1)
{
int k = j + nTranslation;
if (k >= nDataLen)
{
k -= nDataLen;
}
if (k == i)
{
break;
}
array[j] = array[k];
j = k;
}
array[j] = temp;
}
}
2.分段递归交换
旋转向量x其实就是交换向量ab的两段,得到ba(a代表x中的前i个元素)。假设a比b短,将b分为b1和b2两段,使b2有跟a相同的长度,然后交换a和b2,也就是ab1b2交换得到b2b1a,a的位置已经是最终的位置,现在的问题集中到交换b2b1这两段,又回到了原来的问题。不断递归下去,到b1和b2的长度长度相等交换即可。
// 数组中的数据首位两两交换
void swap(int array[], int nStartPos, int nEndPos, int offset)
{
int temp;
for (int i = 0; i < offset; i++)
{
temp = array[nStartPos + i];
array[nStartPos + i] = array[nEndPos + i];
array[nEndPos + i] = temp;
}
}
// 分段递归交换
// array:置换数组
// nDataLen:数组长度
// nTranslation:平移位数
void swapShift(int *array, int nDataLen, int nTranslation)
{
int p = nTranslation;
int i = p;
int j = nDataLen - p;
while (i != j)
{
if (i > j)
{
swap(array, p - i, p, j);
i -=j;
}
else
{
swap(array, p - i, p + j - i, i);
j -= i;
}
}
swap(array, p - i, p, i);
}
3.求逆
利用向量原理:把x向量分成ab两部分,a是前i个元素,b是后n-i个元素,首先对a求逆,得到a-1b,然后对b求逆得到a-1b-1,然后对整体求逆得到(a-1b-1)-1=ba。
void reverse(int array[], int low, int high)
{
int temp = 0;
for(int i = low; i <= (high + low) / 2; i++)
{
temp = array[i];
array[i] = array[high - (i - low)];
array[high - (i - low)] = temp;
}
}
// 求逆
// array:置换数组
// nDataLen:数组长度
// nTranslation:平移位数
void reverseShift(int *array, int nDataLen, int nTranslation)
{
reverse(array, 0, nTranslation - 1);
reverse(array, nTranslation, nDataLen - 1);
reverse(array, 0, nDataLen - 1);
}