完美洗牌算法的多种实现

       非常喜欢看“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;
}




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;
}




结束!!!


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

coffee_baba

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值