约瑟夫问题的由来:
据说著名犹太历史学家 Josephus有过以下的故事:在罗马人占领乔塔特后,39 个犹太人与Josephus及他的朋友躲到一个洞中,39个犹太人决定宁愿死也不要被敌人抓到,于是决定了一个自杀方式,41个人排成一个圆圈,由第1个人开始报数,每报数到第3人该人就必须自杀,然后再由下一个重新报数,直到所有人都自杀身亡为止。然而Josephus 和他的朋友并不想遵从,Josephus要他的朋友先假装遵从,他将朋友与自己安排在第16个与第31个位置,于是逃过了这场死亡游戏。看来功课学得好关键时刻可以救命啊!!! 哈哈。。。
简单实现了一个单链表以对约瑟夫问题的求解。
/*
循环链表:循环单链表
示例:约瑟夫环
*/
typedef struct LNode {
int data; //数据域
LNode *next; //指针域
}LNode,*LinkList;
/*
function:初始化约瑟夫环
*/
LinkList createLinkList(int n) {
LNode *L = NULL;
LNode *s;
LNode *r = NULL;//尾指针
if (n < 1) {
return NULL;
}
//注释这行的目的是为了去除头结点,我们的数据节点从第一个开始
//L = (LinkList)malloc(sizeof(LNode));//头结点
//r = L;
int j = 1;
int x;
scanf_s("%d", &x);
while (j<=n)
{
s = (LinkList)malloc(sizeof(LNode));
s->data = x;
if (L == NULL) {
//初始化第一个节点
L = r = s;
}
else
{
r->next = s;
r = s;
}
if (j == n) {
break;
}
j++;
scanf_s("%d", &x);
}
//指向第一个节点,形成闭环
r->next = L;
return L;
}
/*
function:依次取出满足条件的数据
*/
void printData() {
LNode *p =createLinkList(10);
int j = 1;
int k = 3;//约瑟夫环约定需要处理的节点标号
while (p!=NULL)
{
//p = p->next;//获取下一个节点地址
if (j == (k -1)) {
//达到约瑟夫环的条件需要移除节点的前驱节点
LNode *q = p->next;//需要移除的节点
p->next = q->next;
p = p->next; //指针向前移动一个节点(从下一个节点开始)
printf_s("%d \t", q->data);
free(q);
j == 1;
}
else
{
j++;
}
p = p->next;//获取下一个节点地址
}
}
void main() {
printData();
}
以上为约瑟夫问题循环单链表的基本实现,帮助我们进一步熟悉循环单链表;我们还可以通过更高级的方式实现:递归,好吧,这就留给下次思考和实现了!