(六)循环链表 魔术师发牌 ---- 见证奇迹的时刻到了

魔术师发牌

舞台上:魔术师利用一副牌中的13张黑桃牌(其实神马花色都行),预先给他们排好后叠在一起,肯定是有固定的顺序,牌面朝下面,对观众们说“我不看牌,只需要数一数就可以猜到每张牌是什么~。”
然后呢,魔术师讲最上面的那张牌数为1 ,把它翻过来正好是黑桃A,将黑桃A放在桌子上,第二次数1,2,将第一张牌放在这些牌的下面,将第二张牌翻过来 正好是黑桃2 ,也将它放在 桌子上 ,这样,依次进行下去,13张牌被全部翻出,而且 准确无误。

实际上是这样的。一开始,把有序叠好的牌放在桌面上铺好 一列, 最上面的那张为 黑桃A 也就是 1,然后把它拿出来,扔掉 ,然后从上边取出1张牌放到最底下,打开第二张牌是黑桃2,扔掉;再依次将2张放到底下,第三张是黑桃3,扔掉;依次。。。。。知道最后剩一张牌,黑桃K。

先不要纠结魔术师如何洗牌,洗成固定顺序,咱们先看看是那种顺序能够实现这种神奇的发牌方式。

解决方案:
利用循环链表,初始化13个0的循环链表,第一个为1,然后走两步为2,再走三步为3,再走四步为4,到第五步的时候就出现问题了,已经循环到头部了,这时我们定个规则,如果步过的节点不为0,则跳过,直到0为止。说白了,就是步过的数量,必须是步过0的数量。

#include
#includetypedef struct node
{int data;struct node* next;
}node;node* ghead = NULL;//创建没有头节点的循环链表
void create_list(int num)
{node* ltail = NULL, * lnew = NULL;int i;/*ghead = (node*)malloc(sizeof(node));ltail = ghead;*/for (i = 0; i < num; i++){lnew = (node*)malloc(sizeof(node));lnew->data = 0;if (i == 0){ghead = lnew;lnew->next = lnew;}else{lnew->next = ltail->next;ltail->next = lnew;}ltail = lnew;}
}void printlist(node* ll)
{node* llh = NULL;llh = ll;int i = 1;if (!ll){printf("链表为空");return;}while (ll->next != llh){printf("%d:\t%d\n", i++, ll->data);ll = ll->next;}printf("%d:\t%d\n", i++, ll->data);
}void magicpoker(node* ll)
{int count_step = 0;int i = 0;//第一张始终是1ll->data = 1;count_step = 2;while (1){for (i = 0; i < count_step; i++){ll = ll->next;if (ll->data != 0){i--; //增加循环次数,就变相步过不为0的节点。}}if (ll->data == 0){ll->data = count_step;//ll = ll->next;count_step++;if (count_step == 14){break;}}}
}int main()
{create_list(13);magicpoker(ghead);printlist(ghead);system("pause");
}

结果:

1:      1
2:      8
3:      2
4:      5
5:      10
6:      3
7:      12
8:      11
9:      9
10:     4
11:     7
12:     6
13:     13


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部