約瑟夫(Joseph)環
設計目的:
1.掌握單向循環鏈表的建立。
2.掌握單向循環鏈表的操作。
設計內容:
編號是1,2,……,n的n個人按照順時針方向圍坐一圈,每個人只有一個密碼(正整數)。一開始任選
一個正整數作爲報數上限值m,從第一個仍開始順時針方向自1開始順序報數,報到m時停止報數。報m的
人出列,將他的密碼作爲新的m值,從他在順時針方向的下一個人開始重新從1報數,如此下去,直到所有
人全部出列爲止。請設計一個程序求出出列順序。
設計要求:
1.利用單向循環鏈表存儲結構模擬此過程,按照出列的順序輸出各個人的編號。
2.測試數據:m的初值爲20,n=7,7個人的密碼依次爲3,1,7,2,4,7,4,首先m=6,則正確的輸出是什麼?
3.輸入數據:建立輸入函數處理輸入的數據,輸入m的初值n,輸入每個人的密碼,建立單向循環鏈表。
4.輸出形式:建立一個輸出函數,將正確的出列順序輸出。
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<conio.h>
#include<windows.h>
#define maxmi 10 //每人最大密碼值爲10
#define maxnum 10 //需要處理的最多人數爲10
#define maxsx 20 //初始查找的上限值爲20
typedef struct LinkList
{
int data;
int password;
struct LinkList *next;
} LL;
//函數聲明
void display();
void mueu();
LL *CreatList();
void InitList(LL *,int );
int GetPassword();
int GetPersonNumber();
int GetSX();
void GetOutput(LL *,int , int , int * );
void print(int *,int );
void display()
{
//展示初始界面
printf("\n\n\n\n\n\n");
system("color 7A");
printf(" 歡");
Sleep(250);
system("color 7B");
printf("迎");
Sleep(250);
system("color 7C");
printf("了");
Sleep(250);
system("color 7D");
printf("解");
Sleep(250);
system("color 7E");
printf("約");
Sleep(250);
system("color 7F");
printf("瑟");
Sleep(250);
system("color 7A");
printf("夫");
Sleep(250);
system("color 7B");
printf("環");
Sleep(250);
system("color 7C");
printf("!");
Sleep(250);
system("color 7D");
printf("\n\n");
Sleep(500);
printf(" ——計算機1812班***\n\n");
Sleep(500);
printf(" (請按任意鍵繼續)");
getch();
system("cls");
system("color 70");
}
void menu()
{
//菜單函數
printf(" ————選擇菜單————\n");
printf(" | |\n");
printf(" |請選擇以下功能: |\n");
printf(" | |\n");
printf(" |(1)瞭解約瑟夫環問題 |\n");
printf(" | |\n");
printf(" |(2)實現約瑟夫環 |\n");
printf(" | |\n");
printf(" |(3)退出程序 |\n");
printf(" | |\n");
printf(" ————————————\n");
printf(" 請輸入功能的編號(1-3):");
}
LL *CreatList()
{
//單鏈表的初始化
LL *l;
l = (LL *)malloc(sizeof(LL));
if(l == NULL)
{
printf("內存分配失敗!");
exit(1); //非正常運行導致退出程序
}
return l;
}
void InitList(LL *l,int personNumber)
{
//建立循環單鏈表
LL *p,*q;
int i;
p = l;
p->data = 1;
p->password = GetPassword();
for(i = 2; i <= personNumber; i++)
{
q = (LL *)malloc(sizeof(LL));
if(q==NULL)
{
printf("內存空間分配失敗!");
exit(1);
}
q->password = GetPassword();
q->data = i;
p->next = q;
p = q;
}
p->next = l;
}
int GetPersonNumber()
{
//輸入處理的人數
int personNumber;
printf(" 請輸入人數:");
scanf("%d",&personNumber);
while(personNumber > maxnum || personNumber < 0)
{
printf("\n 對不起,您輸入的數字無效,請輸入在0到%d的整數:",maxnum);
scanf("%d",&personNumber);
}
printf(" 本次求約瑟夫環的出列順序人數爲%d人。\n\n",personNumber);
return personNumber;
}
int GetPassword()
{
//爲每個人賦密碼
int password;
static int count = 1;
printf(" 請輸入第%d人的密碼:",count);
scanf("%d",&password);
while(password > maxmi || password < 0)
{
printf(" 對不起,您輸入的數字無效,請輸入在0到%d的整數:",maxmi);
scanf("%d",&password);
}
count++;
return password;
}
int GetSX()
{
//確定開始的上限
int sx;
printf(" 請輸入報數的上限值:");
scanf("%d",&sx);
while(sx > maxsx || sx < 0)
{
printf("\n 對不起,您輸入的數字無效,請輸入在0到%d的整數:",maxsx);
scanf("%d",&sx);
}
printf(" 最終的報數上限值爲%d。\n\n",sx);
return sx;
}
void GetOutput(LL *l,int personNumber,int sx,int array[maxnum])
{
//得到出隊順序
LL *p,*q;
int count = 1,i = 0;
p = l;
while(personNumber)
{
while(count != sx)
{
q = p;
p = p->next;
count++;
}
array[i++] = p->data;
sx = p->password;
q->next = p->next;
free(p);
p = q->next;
count = 1;
personNumber--;
}
}
void print(int array[],int personNumber)
{
//輸出最終結果
int i;
printf("\n 按每人的編號(1~%d)依次出列的順序爲:",personNumber);
for(i = 0; i < personNumber; i++)
{
printf("%-4d",array[i]);
}
printf("\n");
}
int main()
{
char(ch);
LL *l;
int personNumber,SX;
int array[maxnum];
display();
system("title 約瑟夫環問題");
flag1:
menu();
ch=getchar();
system("cls");
switch (ch)
{
case '1':
printf(" 編號是1,2,……,n的n個人按照順時針方向圍坐一圈,每個人只有一個密碼(正整數)。\n");
printf("一開始任選一個正整數作爲報數上限值m,從第一個仍開始順時針方向自1開始順序報數,\n");
printf("報到m時停止報數。報m的人出列,將他的密碼作爲新的m值,從他在順時針方向的下一個人\n");
printf("開始重新從1報數,如此下去,直到所有人全部出列爲止。\n\n");
printf(" 請按任意鍵繼續");
getch();
system("cls");
break;
case '2':
printf(" ————約瑟夫環問題————\n");
personNumber = GetPersonNumber();
SX = GetSX();
l = CreatList();
InitList(l,personNumber);
GetOutput(l,personNumber,SX,array);
print(array,personNumber);
printf(" 請按任意鍵繼續");
getch();
system("cls");
break;
case '3':
printf(" 謝謝使用,再見!\n");
return 0;
}
goto flag1;
return 0;
}