问题描述:
编号为1~N的N个人按顺时针方向围坐一圈,每个人持有一个密码(正整数,可以自由输入),开始任选一个正整数作为报数上限值M,从第一个人按照顺时针方向自1开始顺序报数,报到M时停止报数。报M的人出列,将他的密码作为新的上限值M,从他顺时针方向的下一个人开始从1报数,如此下去,直至所有人出列为止。
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
using namespace std;
struct node
{
int data;
struct node *next;
};
node * create(int n);
node * createRandom(int n);
void printList(node *p, int n);
void ysfProblem(node *);
node * createRear(int n);
node * connect(node *a, node *b);
int main()
{
int len1=0, len2=0 ,n = 0;
int i =0;
node *a, *b;
printf("请输入您想要创建的表的长度:\n");
cin >> n;
node *p = createRandom(n);
printList(p, n);
ysfProblem(p);
//创建两个尾指针的循环链表
//while (i != 2)
//{
printf("(尾指针)请输入表1的长度:\n");
cin >> len1;
a= createRear(len1);
printf("表1的第一个节点为: %d\n",a->next->data);
printf("(尾指针)请输入表2的长度:\n");
cin >> len2;
b = createRear(len2);
printf("表2的第一个节点为: %d\n", b->next->data);
//AB[i]= createRear(len);
//i++;
//}
//连接表1和表2
node *r = connect(a, b);
printf("连接后的表1和表2:\n");
printList(r,len1+len2);
printf("连接后的表的第一个节点为: %d\n", r->next->data);
return 0;
}
//创建一个数据从1自增的循环链表,返回指向第一个节点的指针node *
node *create(int n) {
node *p = NULL, *head;
head = (node*)malloc(sizeof(node));//分配头结点(指向第一个节点)内存
p = head;
node *s = NULL;
int i = 1;
if (0 != n)
{
while (i <= n)
{
s = (node*)malloc(sizeof(node));
s->data = i++;
p->next = s;
p = s;
}
s->next = head->next;//将最后一个节点指向第一个节点
}
free(head); //当表创建完成以后,就可以释放掉指向第一个节点的指针了,因为通过最后一个节点可以访问到第一个节点
return s->next;
}
//创建一个数据可自己输入的循环链表,返回指向第一个节点的指针node *
node *createRandom(int n) {
node *p = NULL, *head;
//分配一个node大小的空间,并把分配的空间的首地址强制转换成node *指针类型
//执行完毕后head指针将指向该首地址
head = (node*)malloc(sizeof(node));
p = head;
node *s = NULL;
int i = 1;
int input = 0;
if (0 != n)
{
printf("请依次输入%d个正整数:\n", n);
while (i <= n)
{
cin >> input;
s = (node*)malloc(sizeof(node));
s->data = input;
p->next = s;
p = s;
i++;
}
s->next = head->next;//将最后一个节点指向第一个节点
}
free(head); //当表创建完成以后,就可以释放掉指向第一个节点的指针了,因为通过最后一个节点可以访问到第一个节点
return s->next;
}
//创建一个返回尾指针(指向链表的最后一个节点)的循环链表
node * createRear(int n)
{
node *p = NULL, *rear = NULL, *head;
//p = (nodeRear *)malloc(sizeof(nodeRear));
head = (node *)malloc(sizeof(node));
//rear = (node *)malloc(sizeof(node));
p = head;
node *s = NULL;
int i = 1, input = 0;
if (n != 0) {
printf("请依次输入%d个正整数:\n", n);
while (i <= n)
{
cin >> input;
s = (node *)malloc(sizeof(node));
s->data = input;
p->next = s;
p = s;
i++;
}
rear = p;
rear->next = head->next;
}
free(head);
return rear;
}
//连接两个以尾指针创建的链表
node * connect(node *a, node *b)
{
node *temp = a->next;
a->next = b->next;
b->next = temp;
free(temp); //不要忘记释放创建的临时结点!!
return b;
}
//打印第一个节点为p的长度为n的表
void printList(node *p, int n)
{
printf("最初的顺序是:\n");
for (int j = 1; j < n; j++)
{
printf("%d->", *p);
p = p->next;
}
printf("%d\n", *p);
}
//约瑟夫问题,和其衍生问题
void ysfProblem(node *p) {
//m %= n;
node *temp = NULL;
int first = 0;
printf("请选择一个初始上限值M:\n");
cin >> first;
int m = first;
printf("删除顺序是:\n");
while (p != p->next) //终止条件!!
{
if (m == 1)
{
m = p->data;
printf("%d->", p->data);//打印被删除的节点的数据
temp->next = p->next;
p = p->next; //将p指向下一个节点
}
else
{
//从p指向的节点开始,顺序读取到第m-1个节点
for (int i = 1; i < m - 1; i++)
{
p = p->next;
}
m = p->next->data;
if (m == 1)
temp = p;
printf("%d->", p->next->data);//打印第m个节点的数据
p->next = p->next->next;//删除第m个节点
p = p->next; //将p指向被删除的那个人的下一个人
}
}
//当最后只剩一个人时,打印
printf("%d\n", p->data);
}
测试结果: