【数据结构】其四:链表应用求解约瑟夫环问题——2022/01/03
紧赶慢赶,终于在十点前赶出来了……😅总之,先这样交着,明天在自己修改修改。
代码:
#include <stdio.h>
#include <stdlib.h>
#define MAXPV 20
#define MAXNUM 30
#define MAXFV 10
/**
* 注释:
* 项目建立时间:2022/01/03
* 项目名称:通过循环双向链表求解约瑟夫环问题
*/
typedef struct LinkList
{
int data;
int password;
struct LinkList *next;
} LinkList;
LinkList *InitList();
/* 方法声明 */
void CreateList(LinkList *head, int);
int GetPassWord();
int GetPersonNUmber();
int GetFirstCountValue();
void GetOutputOrder(LinkList *, int, int, int *);
void PrintResult(int *, int);
/* 初始化链表 */
LinkList *InitList()
{
LinkList *head;
head = (LinkList *)malloc(sizeof(LinkList));
head->next=head; //这一句对程序无关紧要,没有也可以跑;
return head;
}
/* 根据输入的人数及密码,创建链表 */
void CreateList(LinkList *head, int n)
{
LinkList *s, *p;
p = head;
p->data = 1;
p->password = GetPassWord(); /* 头结点位置需要单独传入序号1及其密码; */
for (int i = 2; i <= n; i++)
{
s = (LinkList *)malloc(sizeof(LinkList));
s->password = GetPassWord();
s->data = i;
p->next = s;
p = s;
}
p->next = head;
}
/* 获取输入的人数 */
int GetPersonNumber()
{
int n;
printf("请输入人数:");
scanf("%d", &n);
while (n > MAXNUM || n < 0)
{
printf("\n你输入的数字无效,请输入在0到%d的整数", MAXNUM);
scanf("%d", &n);
}
printf("本次求约瑟夫环的出列顺序人数为%d人。\n", n);
return n;
}
/* 获取输入的密码 */
int GetPassWord()
{
int password;
static int count = 1;
printf("\n请输入第%d人的密码:", count);
scanf("%d", &password);
while (password > MAXPV || password < 0)
{
printf("你输入的数字无效,请输入在0到%d的整数", MAXPV);
scanf("%d", &password);
}
count++;
return password;
}
//获取输入的密码上限值
int GetFirstValue()
{
int fValue;
printf("请输入密码的上限值:");
scanf("%d", &fValue);
while (fValue > MAXFV || fValue < 0)
{
printf("\n你输入的数字无效,请输入在0到%d的整数", MAXFV);
scanf("%d", &fValue);
}
printf("最终的密码上限值为%d。\n", fValue);
return fValue;
}
/* 将排列好的约瑟夫环的序号存入数组 */
void GetOutputOrder(LinkList *head, int n, int rValue, int array[])
{
LinkList *s, *p;
int count = 1, i = 0;
p = head;
s = InitList();
while (n--)
{
while (count!=value)
{/* 当count不等于输入的密码时,s指向p所指的,p指向下一个,count自增; */
s = p;
p = p->next;
count++;
}
array[i++] = p->data; //将序号存入数组;
value = p->password; //将密码存入value,并作为之后的密码判定;
/* 将值取出,存入array,删除目标p所指结点,再将此时的s链表赋给p,count重置为1; */
s->next = p->next;
free(p);
p = s->next;
count = 1;
}
}
/* 将排好的约瑟夫环数组输出 */
void printResult(int array[], int n)
{
printf("\n按每人持有的编号依次出列的顺序为:");
for (int i = 0; i < n; i++)
{
printf("%-3d", array[i]);
}
printf("\n");
}
/* 将链表元素逐个输出方法 */
void DispList(LinkList *head){
LinkList *p;
p = head->next; //因为把第一个序号和值,都存在了头结点位置,所以需要单独输出。
printf("%5d", head->data);
while (p!=head)
{
printf("%5d", p->data);
p = p->next;
}
printf("\n");
}
int main()
{
LinkList *head;
int n, rValue; //n是总人数;rvalue是初始值;
int array[MAXNUM];
printf("约瑟夫环问题。\n");
n = GetPersonNumber();
rValue = GetFirstValue();
head = InitList();
CreateList(head, n);
GetOutputOrder(head, n, rValue, array);
printResult(array, n);
system("pause"); //暂停程序,按任意键继续;
return 0;
}
以后敲代码还是尽量早吧……晚上老家这灯光不行,怪费眼的。😵
1月4号:
增添了注释和链表元素逐个输出方法,顺便加深了一下印象;尝试使用双向循环链表,看能不能简化代码。可惜研究一天也没有什么进展……😅