非常喜欢看“v_JULY_v”大神的博客,可以说受益颇多。大神博客首页:http://blog.csdn.net/v_july_v?viewmode=contents。
昨天看了“程序员编程艺术第三十四~三十五章:格子取数问题,完美洗牌算法”,稍微实现了下文章提到的几种关于洗牌的算法,记录在此。
关于“完美洗牌”的理论,我在这不多讲了,请看上面的链接,这里只给出我自己实现的代码。
1.位置置换perfect_shuffle1算法
#define NUM 9
char * pa[9] = {NULL,
"a1", "a2", "a3", "a4",
"b1", "b2", "b3", "b4"
};
void display_strings(char * pa[], int n)
{
int i;
for(i = 1; i < n; ++i)
cout << pa[i] <<" ";
cout << endl;
}
void perfect_shuffle1(char * pa[], const int n)
{
int i = 0;
char * pTmp[NUM];
for (i = 1; i < n; ++i)
{
pTmp[2 * i % n] = pa[i];
}
for (i = 1; i < n; ++i)
{
pa[i] = pTmp[i];
}
}
int main()
{
display_strings(pa, 9);
perfect_shuffle1(pa, 9);
display_strings(pa, 9);
return 0;
}
实验结果:
2.分而治之perfect_shuffle2算法
#define NUM 9
char * pa[9] = {NULL,
"a1", "a2", "a3", "a4",
"b1", "b2", "b3", "b4"
};
char * pb[11] = {NULL,
"a1", "a2", "a3", "a4", "a5",
"b1", "b2", "b3", "b4", "b5"
};
void display_strings(char * pa[], int n)
{
int i;
for(i = 1; i < n; ++i)
cout << pa[i] <<" ";
cout << endl;
}
void perfect_shuffle2(char * pa[], int start, int end)
{
int n = (end - start + 1) / 2;
int i = 0, j = 0;
char * tmp;
if (n == 1)
{
return;
}
if (n & 0x01)
{
tmp = pa[n];
for (i = n; i <= 2 * n - 2 ; i++)
{
pa[i] = pa[i + 1];
}
pa[2 * n - 1] = tmp;
n--;
}
for (i = n / 2 + 1, j = 1; i <= n; ++i, j++)
{
tmp = pa[i + start - 1]; pa[i + start - 1] = pa[j + n + start - 1]; pa[j + n + start - 1] = tmp;
}
perfect_shuffle2(pa , 1, n);
perfect_shuffle2(pa , n + 1, 2 * n);
}
int main()
{
cout << "---------------------------------\n";
display_strings(pa, 9);
perfect_shuffle2(pa, 1, 8);
display_strings(pa, 9);
cout << "---------------------------------\n";
cout << "\n";
cout << "---------------------------------\n";
display_strings(pb, 11);
perfect_shuffle2(pb, 1, 10);
display_strings(pb, 11);
cout << "---------------------------------\n";
return 0;
}
3.完美洗牌算法perfect_shuffle3---走圈法
1)递归实现,有点“分而治之”的味道
#define NUM 9
char * pa[9] = {NULL,
"a1", "a2", "a3", "a4",
"b1", "b2", "b3", "b4"
};
char * pb[11] = {NULL,
"a1", "a2", "a3", "a4", "a5",
"b1", "b2", "b3", "b4", "b5"
};
void display_strings(char * pa[], int n)
{
int i;
for(i = 1; i < n; ++i)
cout << pa[i] <<" ";
cout << endl;
}
void cycle(char * pa[], int start, int mod)
{
char * last = pa[start], * tmp;
int i;
for (i = 2 * start % mod ; i != start; i = 2 * i % mod)
{
tmp = pa[i];
pa[i] = last;
last = tmp;
}
pa[start] = tmp;
}
void rotate_right(char * a[], int from, int to)
{
char * tmp;
for (; from < to; ++from, --to)
{
tmp = a[from]; a[from] = a[to]; a[to] = tmp;
}
}
void perfect_shuffle3(char * a[], const int n)
{
int m, k, i, order;
if(n == 0)
return;
for (k = 0, order = 1; order <= 2 * n + 1; )
{
++k;
order *= 3;
}
k--;
m = (order / 3 - 1) / 2;
rotate_right(a, m + 1, n);
rotate_right(a, n + 1, n + m);
rotate_right(a, m + 1, n + m);
for (i = 0, order = 1; i < k; ++i)
{
cycle(a, order, 2 * m + 1);
order *= 3;
}
perfect_shuffle3(a + 2 * m, n - m);
}
int main()
{
cout << "---------------------------------\n";
display_strings(pa, 9);
perfect_shuffle3(pa, 4);
display_strings(pa, 9);
cout << "---------------------------------\n";
cout << "\n";
cout << "---------------------------------\n";
display_strings(pb, 11);
perfect_shuffle3(pb, 5);
display_strings(pb, 11);
cout << "---------------------------------\n";
return 0;
}
#define NUM 9
char * pa[9] = {NULL,
"a1", "a2", "a3", "a4",
"b1", "b2", "b3", "b4"
};
char * pb[11] = {NULL,
"a1", "a2", "a3", "a4", "a5",
"b1", "b2", "b3", "b4", "b5"
};
void display_strings(char * pa[], int n)
{
int i;
for(i = 1; i < n; ++i)
cout << pa[i] <<" ";
cout << endl;
}
void cycle(char * pa[], int start, int mod)
{
char * last = pa[start], * tmp;
int i;
for (i = 2 * start % mod ; i != start; i = 2 * i % mod)
{
tmp = pa[i];
pa[i] = last;
last = tmp;
}
pa[start] = tmp;
}
void rotate_right(char * a[], int from, int to)
{
char * tmp;
for (; from < to; ++from, --to)
{
tmp = a[from]; a[from] = a[to]; a[to] = tmp;
}
}
void perfect_shuffle3(char * a[], const int n)
{
int m, k, i, order;
if(n == 0)
return;
for (k = 0, order = 1; order <= 2 * n + 1; )
{
++k;
order *= 3;
}
k--;
m = (order / 3 - 1) / 2;
rotate_right(a, m + 1, n);
rotate_right(a, n + 1, n + m);
rotate_right(a, m + 1, n + m);
for (i = 0, order = 1; i < k; ++i)
{
cycle(a, order, 2 * m + 1);
order *= 3;
}
perfect_shuffle3(a + 2 * m, n - m);
}
int main()
{
cout << "---------------------------------\n";
display_strings(pa, 9);
perfect_shuffle3(pa, 4);
display_strings(pa, 9);
cout << "---------------------------------\n";
cout << "\n";
cout << "---------------------------------\n";
display_strings(pb, 11);
perfect_shuffle3(pb, 5);
display_strings(pb, 11);
cout << "---------------------------------\n";
return 0;
}
2)看了“v_JULY_v”的代码,感觉完全没必要用到递归,故修改了源代码,得到“迭代”版本。
#define NUM 9
char * pa[9] = {NULL,
"a1", "a2", "a3", "a4",
"b1", "b2", "b3", "b4"
};
char * pb[11] = {NULL,
"a1", "a2", "a3", "a4", "a5",
"b1", "b2", "b3", "b4", "b5"
};
void display_strings(char * pa[], int n)
{
int i;
for(i = 1; i < n; ++i)
cout << pa[i] <<" ";
cout << endl;
}
void cycle(char * pa[], int start, int mod)
{
char * last = pa[start], * tmp;
int i;
for (i = 2 * start % mod ; i != start; i = 2 * i % mod)
{
tmp = pa[i];
pa[i] = last;
last = tmp;
}
pa[start] = tmp;
}
void rotate_right(char * a[], int from, int to)
{
char * tmp;
for (; from < to; ++from, --to)
{
tmp = a[from]; a[from] = a[to]; a[to] = tmp;
}
}
void perfect_shuffle4(char * a[], int n)
{
int m, k, i, order;
while (n > 0)
{
for (k = 0, order = 1; order <= 2 * n + 1; )
{
++k;
order *= 3;
}
k--;
m = (order / 3 - 1) / 2;
rotate_right(a, m + 1, n);
rotate_right(a, n + 1, n + m);
rotate_right(a, m + 1, n + m);
for (i = 0, order = 1; i < k; ++i)
{
cycle(a, order, 2 * m + 1);
order *= 3;
}
a += 2 * m;
n -= m;
}
}
int main()
{
cout << "---------------------------------\n";
display_strings(pa, 9);
perfect_shuffle4(pa, 4);
display_strings(pa, 9);
cout << "---------------------------------\n";
cout << "\n";
cout << "---------------------------------\n";
display_strings(pb, 11);
perfect_shuffle4(pb, 5);
display_strings(pb, 11);
cout << "---------------------------------\n";
return 0;
}
结束!!!