数据结构-单向循环链表
单向循环循环链表实现约瑟夫问题
X个人围成一圈,每个人手里都有不同的密码,选择一个人,从他开始,以他的密码为初始开始报数,如果有人报的数字为1,这个人退出并且以退出这个人手中的密码作为新的起始,直到所有人都出列他为止
单项循环链表实现
#include "stdafx.h" //头文件 不说了
struct man
{
int num; //序号
int password; //数据域
struct man *next; //指针域
};
typedef struct man Node;
typedef Node* Ptr;
int main()
{
Ptr head;
int num;
Ptr CreatLink(int num);
void Show(Ptr head, int num);
printf_s("请输入人数:");
scanf_s("%d", &num);
head = CreatLink(num);
Show(head, num);
return 0;
}
Ptr CreatLink(int num)
{
int i;
Ptr head, previous, last; //头,当前,尾指针
head = (Ptr)malloc(sizeof(Node)); //给头结点分配空间
if (head == NULL) //创建失败报错
{
printf_s("wrong!");
return NULL;
}
last = head; //将头结点的地址赋值给尾结点
for (i = 0; i < num; i++) //循环输入所有人的密码放到对应的结点的对应数据域(对应的次序)
{
previous = last; //把尾结点的地址复制到当前指针
printf_s("请输入第%d个人的密码", i + 1);
scanf_s("%d", &previous->password); //把所的密码依次存入对应结点的数据区
previous->num = i + 1; //对应序号加一
last = (Ptr)malloc(sizeof(Node)); //为last创建新的结点(为了存入新的数据)
if (last == NULL) //创建失败报错
{
printf_s("wrong!");
return NULL;
}
previous->next = last; //链接结点,使得上一个last结点(复制给previous)的指针域指向新的last结点
}
previous->next = head; //循环结束,多余的结点不需要,最后一个结点直接指向头结点,形成循环
free(last); //释放多余的结点
last = previous; //最后一个结点复制给last结点
return last;
}
void Show(Ptr head, int num)
{
int num1, i, j; //num1是报数的人的序号
Ptr previous, last; //当前指针和尾指针
last = head->next; //尾指针直接指向头指针的下一个结点
previous = head; //头指针复制给当前指针
printf_s("请输入第一个报数的人:");
scanf_s("%d", &num1);
printf_s("输出顺序为:");
for (i = num; i > 0; i--) //人数递减
{
for (j = num1; j > 1; j--) //密码递减
{
previous = last; //尾指针成为当前指针
last = last->next; //下一个指针成为尾指针
}
previous->next = last->next; //尾指针的下一个指针复制给当前指针的下一个指针
printf_s("%d", last->num); //打印尾指针的数据域的序号
num1 = last->password; //将尾指针数据域的密码赋值给num1;
free(last); //释放尾指针
last = previous->next; //将当前指针的指针域next指向尾指针
}
}