typedef int data_t;
typedef struct linklist
{
data_t data;
struct linklist *next;
}Linklist; //自定义的结构体作为节点
int main(int argc, char *argv[])
{
Linklist * head = Linklist_create();
//调用函数创建一个节点初始的单个“自闭”链环,具体函数见下文
Linklist *p = head;
Linklist *q = NULL;
for(int i = 15;i > 1;i--)
{
Linklist_insert_head(head,i);
} //用头插法生成一个15个元素的单向循环链表
int lenth = Linklist_lenth(head);
/*得到该链表元素个数,这里事先知道元素个数,但为了解决约瑟夫问题的泛用性*/
printf("lenth = %d\n",lenth);
Linklist_show(head); //查看一下所生成的单向循环链表
int flag = 1; //定义一个标志位
while(lenth > 1) //当仅剩唯一1个元素时停止循环
{
p = p->next; //p指针移动寻找将要被删除的节点的上一个节点
q = p->next; //q指针移动寻找将要被删除的节点
flag++;
if(flag == 3) //当flag计数到3时,q已经指向将要被删除的节点,p指向其上一个节点
{
printf("%d ",q->data); //打印将要被删除的节点数据
Linklist_delet_pos(p,0); //把p所指向的节点当作有头单链表的表头,删除其下标为0的节点 // 具体实现功能见下文
lenth--; //每删除一个,链表元素个数-1
flag = 0; //重置标志位,标志位计数逻辑可以根据删除之后p指针位置画图分析
}
}
puts("");
Linklist_show(p);//打印最终剩下的这个节点的元素
return 0;
}
/*以下是上文所使用到的自定义函数的具体功能代码*/
Linklist *Linklist_create()
{
Linklist *head = (Linklist *)malloc(sizeof(Linklist));
if(head == NULL)
{
perror("malloc");
return NULL;
}
head->data = 1;
head->next = head;
return head;
}
int Linklist_lenth(Linklist *head)
{
int i = 1;
Linklist *p = head;
while(p->next != head)
{
p = p->next;
i++;
}
return i;
}
void Linklist_insert_head(Linklist *head,data_t data)
{
Linklist *new = (Linklist *)malloc(sizeof(Linklist));
if(new == NULL)
{
perror("malloc");
return;
}
new->data = data;
new->next = NULL;
new->next = head->next;
head->next = new;
return;
}
void Linklist_delet_pos(Linklist *head,int pos)
{
Linklist *p = NULL;
Linklist *q = head;
int i=0;
while(i < pos)
{
q = q->next;
if(q == NULL)
{
printf("error post\n");
return;
}
i++;
}
p = q->next;
q->next = p->next;
free(p);
p = NULL;
return;
}
void Linklist_show(Linklist *head)
{
Linklist *p = head;
while(p->next != head)
{
printf("%d ",p->data);
p = p->next;
}
printf("%d ",p->data);
puts("");
return;
}