约瑟夫问题是个有名的问题:n个人围成一圈,从第k个开始报数,报数m个将被杀掉,从下一个开始报数m,最后剩下一个。
运行结果:
该问题的主要算法func2.c,clinklist.c为单向循环链表的相关操作。
/*
func2.c
*/
#include "func2.h"
void func2(int n,int k, int m)
{
//创建循环链表 表示人群
CLinkList *head = Create_CLinklist();
//人员加入
printf("Input %d people ID[SPACE]:\n",n);
int i,id;
int tail = CLinklist_Length(head)+1; //初始人数0,tail指向位置1
for(i = 1; i <= n; i++){
scanf("%d",&id);
CLinklist_Insert_Pos(head,tail,id); //尾插
tail++; //尾插标记+1
}
//start 指向开始位置结点
Node *start = head;
while(k--){
start = start->next;
}
//删除头节点
Node *p = head;
while(p->next != head){
//遍历指向尾结点
p = p->next;
}
p->next = head->next;
free(head);
//开始
printf("先淘汰的: ");
int j;
while(start->next != start){
//只有一个结点时 退出
j = m-1;//控制start指向要删除结点的上一个位置
while(--j) start = start->next;
printf("%d ",start->next->data);//打印出即将删除的结点
CLinklist_Delete_Add(start);//删除结点 输入前一个结点地址
start = start->next;//下一次 从下一个结点开始
}
//打印出最后活着的
printf("\n最后活着的: %d\n",start->data);
}
/*
main.c
*/
#include "clinklist.h"
int main()
{
int n; //初始总人数
int k; //开始位置
int m; //报数
printf("n-总人数 k-开始位置 m-报数\n");
printf("Input n k m[SPACE]: ");
scanf("%d %d %d",&n,&k,&m);
func2(n,k,m);
return 0;
}
/*
func2.h
*/
#ifndef __FUNC2__
#define __FUNC2__
void func2(int n,int k, int m);
#endif