选老大。N个游戏者围成一圈,从第一个人开始顺序报数1,2,3。凡报道3者退出圈子,最后留在圈中的人为首领。
思路
创建一个包含N个结点的单循环链表来模拟N个人围成的圈,如下图所示。其中结点的数据域存放游戏者的编号,该链表不设头结点,头指针为head。
在程序中,以删除结点代表人退出圈子,设置整形变量c用于计数,指针变量开始时指向head。p每向后一个结点,c加1。当c=2时,就删除下一个结点(报道3者退出圈子)。如下图
代码如下:
#include "pch.h"
#include <iostream>
#include<stdlib.h>
typedef struct node {
int id; /*游戏者的编号*/
struct node*next;
}NODE, *LinkList;
LinkList create_list(int n)
/*创建一个节点数为n的单循环链表,返回值为游戏编号为1的结点的指针*/
{
LinkList head, p;
int k;
head = (NODE*)malloc(sizeof(NODE));/*创建循环列表的第一个结点*/
if (!head) {
printf("memory allocation error!\n"); return NULL;
}
head->id = 1; head->next = head;
for (k = n; k > 1; --k) {/*尾插法创建循环链表的其余n-1个结点*/
p = (NODE*)malloc(sizeof(NODE));
if (!p) {
printf("memory allocation error!\n"); return NULL;
}
p->id = k; p->next = head->next; head->next = p;
}
return head;
}
void play(LinkList head, int n)
{
LinkList p, s;
int c = 0, k;
p = head; c = 1; k = n;
while (k>1)
{
if (c == 2) /*当c等于2时,p指向的结点的后继即为将被删除的结点*/
{
s = p->next; p->next = s->next;
printf("%4d", s->id); free(s);
c = 0; k--;
}
c++; p = p->next;
}
printf("\n%4d was the winner,", p->id); /*输出最后留在圈子内的游戏者编号*/
}
void output(LinkList head) /*输出链表中结点的数据*/
{
LinkList p;
p = head;
do {
printf("%4d", p->id); p->next;
} while (p != head);
printf("\n");
}
int main()
{
LinkList headptr;
int n;
printf("input the number of players:"); scanf_s("%d", &n);
headptr = create_list(n); /*创建单循环列表*/
if (headptr) {
output(headptr); /*输出单循环列表中的结点的信息*/
play(headptr, n);
}
return 0;
}
运行结果:
游戏结束时,链表还有一个节点,这就是老大!