數據結構課程設計——約瑟夫環

約瑟夫(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; 
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章