向量旋转,即循环移位。以下是《编程珠玑》所示的算法。
#include <iostream>
#include <sstream>
#include <vector>
#include <algorithm>
#define _USE_MATH_DEFINES
#include <math.h>
#include <windows.h>
using namespace std;
int gcd(int m, int n)
{
if(m < n){
swap(m, n);
}
while( n > 0){
m = m % n;
swap(m, n);
}
return m;
}
void ShiftLeft(char* pStr, int iNum)
{
int len = strlen(pStr);
for (int i = 0; i < gcd(iNum, len); i++)
{
char tmp = pStr[i];
int j = i;
do
{
int iNext = (j + iNum) % len;
pStr[j] = (iNext == i) ? tmp : pStr[iNext];
j = iNext;
}while ( j != i);
}
}
inline void Reverse(char* pStr, int iLen)
{
for (int i = 0; i < (iLen >> 1); i++)
{
pStr[i] = pStr[iLen - i - 1];
}
}
inline void Reverse2(char* pStr, int iLen)
{
char* pStrRight = pStr + iLen - 1;
while (pStr < pStrRight)
{
swap(*pStr++, *pStrRight--);
}
}
void ShiftLeft2(char* pStr, int iNum)
{
int len = strlen(pStr);
Reverse(pStr, iNum);
Reverse(pStr + iNum, len - iNum);
Reverse(pStr, len);
}
void ShiftLeft3(char* pStr, int iNum)
{
int len = strlen(pStr);
Reverse2(pStr, iNum);
Reverse2(pStr + iNum, len - iNum);
Reverse2(pStr, len);
}
int main(int argc,char** argv)
{
const static int TEST_COUNT = 10000;
DWORD dwStart = GetTickCount();
for (int iCount = 0; iCount < TEST_COUNT; iCount++)
{
char sz[] = "abcdefghijklmnopqrstuvwxyz";
for (int i = 0; i < sizeof(sz) - 1; i++)
{
ShiftLeft(sz, i);
}
}
DWORD dwEllapse = GetTickCount() - dwStart;
cout << "Trick Reverse: " << dwEllapse << " ms" << endl; // 281 ms
dwStart = GetTickCount();
for (int iCount = 0; iCount < TEST_COUNT; iCount++)
{
char sz[] = "abcdefghijklmnopqrstuvwxyz";
for (int i = 0; i < sizeof(sz); i++)
{
ShiftLeft2(sz, i);
}
}
dwEllapse = GetTickCount() - dwStart;
cout << "Three Reverse: " << dwEllapse << " ms" << endl; // 31 ms
dwStart = GetTickCount();
for (int iCount = 0; iCount < TEST_COUNT; iCount++)
{
char sz[] = "abcdefghijklmnopqrstuvwxyz";
for (int i = 0; i < sizeof(sz); i++)
{
ShiftLeft3(sz, i);
}
}
dwEllapse = GetTickCount() - dwStart;
cout << "Three Reverse2: " << dwEllapse << " ms" << endl; // 31 ms
system("pause");
return 0;
}