/*
问题:约瑟夫问题 共有n个人,数到第m个人出局
要求:用单向循环链表来模拟此过程,打印出最后剩下的人的编号
验证: n=11, m=3,则输出为7
2019.2.27 9:20-10:20(60)
*/
/*
思考:自己用的是带头结点的单链表,所以删除的时候,之前没有考虑
到头结点的next成员的值变化,导致程序出错,最后经过debug,成功修改。
答案是直接建立的不带头结点链表,这样感觉更方便一点
*/
#include<stdio.h>
#include<malloc.h>
typedef struct LNode{
int number;
struct LNode *next;
}LNode;
int yueSeFuQuestion(int n, int m);
void showData(LNode *head, int n);
//输出链表
void showData(LNode *head, int n){
int i;
LNode *p;
for(i = 0, p = head->next; i < n; i++, p = p->next){
printf("%d ", p->number);
}
printf("\n");
}
int yueSeFuQuestion(int n, int m){
LNode *p = NULL; //p指向新建立的结点 遍历链表
LNode *q = NULL; //q指向末结点
LNode *head = NULL;
int i;
//构造头结点
p = (LNode *)malloc(sizeof(LNode));
//p->next = NULL;
head = p;
q = p;
//建立链表
for(i = 0; i < n; i++){
p = (LNode *)malloc(sizeof(LNode));
p->number = i+1;
q->next = p;
q = p;
}
q->next = head->next;
//输出链表
showData(head, n);
//遍历链表
p = head;
i = 0;
while(head->next != (head->next)->next){//while(链表里不止一个元素){
q = p;
p = p->next;
i++;
if(i == m){
//删除该结点
if(p == head->next){
q->next = p->next;
head->next = p->next;
}else{
q->next = p->next;
}
free(p);
p = q;
i = 0;
showData(head, --n);
}
}
return (head->next)->number;
}
void main(void){
printf("最后剩下的人为:%d", yueSeFuQuestion(11, 3));
}