用顺序表实现春晚魔术

引个言

NS3系列许久没有更新,一方面是回到家后各种琐事忙忙碌碌,另一方面也是最主要的就是,好吧我懒。(欧耶)

一边好好过年,一边好好规划,后续科研方面可能会分享NS3-Gym的相关应用,应该,应该哈~

回归主题,其实春晚是没怎么好好看的,小尼的“对不上”算是认真观看的一大因素。正好最近在跟着大佬的课重温数据结构,一边看课一边搓搓leetcode的简单题目,也算轻松自在。恰好博主更新了顺序表的相关课程,于是就跟着复盘一下,分享一波~(归根结底不是我想出来的哈)

附上博主主页英雄哪里出来-CSDN博客

见证奇迹

首先定义数组a,里面放着手里的四张牌,定义一个计数器cnt,while结构中是一个迭代100次的“洗牌逻辑”,通过随机数取余得到0-3的x和y,通过中间变量tmp完成索引为x和y的元素交换,相当于洗牌啦。

    int a[4] = { 2,7,6,5 };
    int cnt = 0;
	while (cnt++ < 100)
	{
		int x = rand() % 4;
		int y = rand() % 4;
		int tmp = a[x];
		a[x] = a[y];
		a[y] = tmp;
	}

定义数组b,通过循环把a拷贝到b,也就是把手里的牌撕开。

    int b[4];
	for (int i = 0; i < 4; ++i)
	{
		b[i] = a[i];
	}

定义一个数组c,这里定义的容量比较大,也是为了后续插牌操作有足够的空间。

l和r分别表示开头和结尾,通过两次for循环把数组ab,放入c中。


	int c[1000];
	int l = 0, r = 0;
	for (int i = 0; i < 4; ++i)
	{
		c[r++] = a[i];
    }
	for (int i = 0; i < 4; ++i)
	{
		c[r++] = b[i];
	}

连续两次把第一个元素放在最后

	c[r++] = c[l++];
	c[r++] = c[l++];

首先把c中最后三个元素往后移3个位置,我朝佩服博主的代码这样简练,上述过程中使用r和l后都+1,保证指针始终指向首尾。随后将c中前3个元素插入到空出来的位置,随后l与r都加3,保持首尾指向。

	c[r] = c[r - 3];
	c[r + 1] = c[r - 2];
	c[r + 2] = c[r - 1];

	c[r - 3] = c[l];
	c[r - 2] = c[l + 1];
	c[r - 1] = c[l + 2];

	l += 3;
	r += 3;

把数组第一个元素放在屁股底下(说实话博主这变量名一绝),“南方人”取第一张牌随便找个位置插入(这里默认是插入到倒数第二个位置,其实没有关系,后面通过调试我们可以发现中间元素的顺序没有关系),最后把尾指针r+1。我记着节目中还有基于名字、性别的插入操作,但基本逻辑一致。博主通过头指针后移来等价丢牌操作,此处++l代表男人拿起一张牌丢掉。

	int pigudixia = c[l++];
	
	int x = c[l++];
	c[r] = c[r - 1];
	c[r - 1] = x;
	++r;
	
	++l;

丢牌之后把第一张牌放在最后,反复数次,随后就开始念咒语:“好运留下来,烦恼丢出去~"

	cnt = 0;
	while (cnt++ < 7)
	{
		c[r++] = c[l++];
	}
	cnt = 0;
	while (cnt++ < 5)
	{
		c[r++] = c[l++];
		//好运留下来
		print(c,l,r);
		l++;
		//烦恼丢出去
		print(c,l,r);
	}

让我们看看最后的结果: 2 2

	cout << pigudixia << ' ' << c[l] << endl;

怎么个回事

作者编写了一个输出函数用于观察数组的变化过程,这里发现基于头尾指针的思想真的很方便

void print(int c[],int l,int r)
{
	for(int i = l; i < r; i ++)
	{
		cout << c[i] << ' ' ;
	}
	cout << endl;
}

这里附上完整代码,其中加入了输出函数,用于观察整个过程:

#include<iostream>

using namespace std;

void print(int c[],int l,int r)
{
	for(int i = l; i < r; i ++)
	{
		cout << c[i] << ' ' ;
	}
	cout << endl;
}

int 
main()
{
	int a[4] = { 2,7,6,5 };
	int cnt = 0;
	while (cnt++ < 100)
	{
		int x = rand() % 4;
		int y = rand() % 4;
		int tmp = a[x];
		a[x] = a[y];
		a[y] = tmp;
	}
	// 迭代一百次,实现打乱效果
	int b[4];
	for (int i = 0; i < 4; ++i)
	{
		b[i] = a[i];
	}
	//把a的元素拷贝给b

	int c[1000];
	int l = 0, r = 0;
	//滚动数组c,l、r分别代表数组的边界,左闭右开
	for (int i = 0; i < 4; ++i)
	{
		c[r++] = a[i];
	}
	//把a数组插入到c数组的尾部

	for (int i = 0; i < 4; ++i)
	{
		c[r++] = b[i];
	}
	//把b数组插入到c数组的尾部

	c[r++] = c[l++];
	c[r++] = c[l++];
	//连续两次把第一个数据插入在最后
	
	print(c,l,r);
	//打印一次

	c[r] = c[r - 3];
	c[r + 1] = c[r - 2];
	c[r + 2] = c[r - 1];
	//将数组最后三个元素后移3个位置

	c[r - 3] = c[l];
	c[r - 2] = c[l + 1];
	c[r - 1] = c[l + 2];
	//将数组头三个元素插入到空出来的位置

	l += 3;
	r += 3;
	//l、r各右移三个位置
	
	print(c,l,r);

	int pigudixia = c[l++];
	//把数组头元素存储在屁股底下

	int x = c[l++];
	c[r] = c[r - 1];
	c[r - 1] = x;
	++r;
	//南方人取数组头元素随便找个位置插入

	++l;
	//男人拿起一张扔掉
	
		print(c,l,r);

	cnt = 0;
	//计数器准备
	while (cnt++ < 7)
	{
		c[r++] = c[l++];

	}
	//每次循环把第一个元素放在最后
		print(c,l,r);

	cnt = 0;
	while (cnt++ < 5)
	{
		c[r++] = c[l++];
		//好运留下来
		print(c,l,r);
		l++;
		//烦恼丢出去
		print(c,l,r);
	}
	cout << pigudixia << ' ' << c[l] << endl;

	return 0;
}

运行结果如下:

6 7 5 2 6 7 5 2  //初始
2 6 6 7 5 7 5 2 
7 5 7 5 6 2 
5 7 5 6 2 7 
7 5 6 2 7 5 
5 6 2 7 5 
6 2 7 5 5 
2 7 5 5 
7 5 5 2 
5 5 2 
5 2 5 
2 5 
5 2 
2 // 底牌
2 2 // 屁股底下和底牌成功对上

龙年大吉

在这里只是简单地搬运了博主的代码,加了些自己的注释,供我们学习参考,最近在跟博主的C++数据结构课程,真心感觉不错,让我惊喜的是博主课程还能以这样的方式进行更新,博主真的很用心(单纯平心而论,并无任何意图)。

最后祝我们龙年大吉,每天都是大晴天~

  • 19
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值