【数据结构与算法课程设计】运动比赛的时间安排问题

设计目的

《数据结构》课程主要介绍最常用的数据结构,阐明各种数据结构内在的逻辑关系,讨论其在计算机中的存储表示,以及在其上进行各种运算时的实现算法,并对算法的效率进行简单的分析和讨论。进行数据结构课程设计要达到以下目的:

  • 了解并掌握数据结构与算法的设计方法,具备初步的独立分析和设计能力;
  • 初步掌握软件开发过程的问题分析、系统设计、程序编码、测试等基本方法和技能;
  • 提高综合运用所学的理论知识和方法独立分析和解决问题的能力;
  • 训练用系统的观点和软件开发一般规范进行软件开发,培养软件工作者所应具备的科学的工作方法和作风。

任务概述

设某田径比赛共有m个比赛项目,规定每个选手至多可参加三个项目,有n人报名参加比赛。设计比赛日程表,使得比赛能在尽可能短的时间内完成。要求:m个比赛项目及人员的报名情况表均事先存储在文件中,需要用数据时从文件中读取。
将参赛运动员的报名信息录入到文件里,并且用邻接矩阵输出,然后使用Welch-Powell算法对无向图进行着色,将同一运动员参赛的不同项目安排在不同时间内,减少冲突,最后,按照时间顺序输出运动项目。

本课程设计需要采用算法/函数:

1.无向图的着色问题,使用在离散数学中所学的Welch-Powell算法(即韦尔奇·鲍威尔算法)。
①将图的节点按照度数的递减顺序进行排列,相同度数的排列无顺序要求。
②对第一个点着色,并找到与之不相邻的、在序列中与它最近的点,着相同的颜色。依次类推,对序列中与以着色顶点不相邻的店按照此步骤依次进行。
③除去第一种着色的点,对尚未着色的点1采取步骤2的方法继续着色。
④直到所有顶点已着色,算法结束。

2.文件读写函数。
创建一个文件记录参赛运动员的报名信息,使用文件读取函数读取出来,存储到邻接矩阵中。

本设计采用的数据结构

采用二维数组的顺序存储结构,用邻接矩阵来存储图的相关数据。

结构体的定义:
(1)

   	int number; 
   	int item; //度  
   	int color;  //颜色  
}node;

其中:

1)	number表示记录参赛运动员的报名情况
2)	item表示一个参赛项目的度数
3)	color表示该参赛项目的着色,不发生冲突的参赛项目是一个颜色。

(2)

struct Race{
char name[MAX];
};

其中:

name用来存储比赛项目的名字。

系统功能模块结构图及主要函数说明

系统功能模块结构图

该系统功能模块结构图如图4-1所示:
image
图 4 - 1系统功能模块图

系统流程图

该系统流程图有五个方面:输入数据,转化为邻接矩阵,着色,输出结果,具体系统流程图如图4-2所示:
image
图4 – 2 系统流程图

系统主要函数说明

1 系统全部函数功能介绍

1)	int Draw(int k,int color); 对已经输入的数据使用Welch-Powell算法进行画图
2)	void Start_Screen();打印开始界面
3)	void Finish_Screen();打印结束界面
4)	int Menu();打印菜单界面,并返回用户选择的菜单序号
5)	void DataFromFile();接受用户从文件中导入数据
6)	void DataFromKeyboard();接受用户从键盘输入数据
7)	int cmp(const void *a,const void *b);比较结构体中的颜色,为后序颜色排序做准备
8)	int PrintAdjMatrix();打印邻接矩阵
9)	int ShortTime();打印安排的时间

2 主要函数说明

1) main()函数

main()函数是一个程序的主函数,其功能是根据用户选择菜单序号,调用相关函数,将用户输入的数据进行转换,并将时间安排好,输出相关数据。
main()函数的N-S图如图4-3所示:
image
图 4 - 3 main()函数N-S图

2) DataFromKeyboard()函数

DataFromKeyboard()函数的主要功能是:接受用户从键盘输入的数据,并根据用户输入的数据转换为邻接矩阵,并且根据创建的邻接矩阵调用draw()函数进行图的着色。
DataFromKeyboard()函数的N-S图如图4-4所示:
image
图 4 - 4 DataFromKeyboard()函数 N-S图

3) DataFromFile()函数

DataFromFile()函数的主要功能是:接受用户从文件中导入的数据,并根据用户导入的数据转换为邻接矩阵,并且根据创建的邻接矩阵调用draw()函数进行图的着色。
DataFromFile()函数的N-S图如图4-5所示:
image
图 4 - 4 DataFromFile()函数 N-S图

Draw()函数

Draw()函数的主要功能是,根据邻接矩阵,对不相邻的图进行着色,Draw()函数的N-S如图4-6所示
image
图 4 - 6 Draw()函数N-S图

程序运行数据及其结果

开始界面,菜单界面,结束界面展示:

本程序的开始界面如图5-1所示,菜单界面如图5-2所示,结束界面如图5-3所示。
image
图 5 - 1开始界面

image
图 5 - 2菜单界面

image
图 5 - 2结束界面

从键盘输入数据

输入的数据为:

6 5 1
2 6
4 3 6
2 4 7
9 2 6
3 6

输入数据的截图如图5-4所示,该数据的邻接矩阵如图5-5所示,该数据安排的时间如图5-6所示。
image
图 5 - 4输入数据

image
图 5 - 5该数据的邻接矩阵

image
图 5 - 6该数据安排的时间图

从文件录入数据

本程序需要用户按照格式进行文件编辑,并且文件名由用户自定义,然后输入到程序中,进行数据录入。
数据在文件中的格式如图5-7所示,将文件中的数据录入到程序中如图5-8所示,该数据的邻接矩阵图如图5-9所示,该数据所安排的时间如图5-10所示。
image
图 5 - 7数据在文件中的格式

image
图 5 - 8 将文件中的数据录入到程序中

image
图 5 -9该数据的邻接矩阵图

image
图 5 -10该数据所安排的时间

附录

程序代码:

#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <windows.h>
#include <stdlib.h>

using namespace std;

//******************************************自定义符号常量******************************************* 

#define OVERFLOW -2         //内存溢出错误常量
#define ILLEGAL -1          //非法操作错误常量 
#define OK 1                //表示操作正确的常量 
#define ERROR 0             //表示操作错误的常量
#define MAX  20				//最大比赛项目数量 

//******************************************需要的结构体********************************************

struct Node{   
   int number; 
   int item; //度  
   int color;  //颜色  
}node[MAX];

struct Race{
	char name[MAX];
};

//******************************************自定义符号常量******************************************* 

int a[MAX][MAX]={0};
int i , j , x;
FILE *filep;
FILE *f;
int b[3] , item , temp;
char c , ch;
bool flag = false;//判断用户是否输入数据 

//******************************************自定义函数类******************************************* 

int Draw(int k,int color); 
int cmp(const void *a,const void *b);
void Start_Screen();
void Finish_Screen();
int Menu();
void DataFromFile();
void DataFromKeyboard();
int PrintAdjMatrix();
int ShortTime();

//******************************************主程序*************************************************
int main()
{
	Start_Screen(); 
	system("color 7");
	
	while( true )
	{
		int num = Menu();
		
		switch(num)
		{
			case 1:{//从键盘中输入数据
				system("CLS");
				DataFromKeyboard(); 
				break;
			}
			case 2:{//从文件中导入数据
				system("CLS");
				DataFromFile();
				break;
			}
			case 3:{//输出邻接矩阵
				if( flag != true)
				{
					cout << "\t||                                                                            ||\n";
					cout << "\t||                       您还未输入数据,请选择 1 或 2                        ||\n";
					cout << "\t||                                                                            ||\n";
					cout << "\t =============================================================================\n\n\n\n";
					cout << "正在为您跳转到主菜单,请稍等...";
					Sleep(2500);
					system("CLS");
					continue;	
				} 
				system("CLS");
				PrintAdjMatrix();
				break;
			}
			case 4:{//输出安排的时间 
				if( flag != true)
				{
					cout << "\t||                                                                            ||\n";
					cout << "\t||                       您还未输入数据,请选择 1 或 2                        ||\n";
					cout << "\t||                                                                            ||\n";
					cout << "\t =============================================================================\n\n\n\n";
					cout << "正在为您跳转到主菜单,请稍等...";
					Sleep(2500);
					system("CLS");
					continue;
				}
				system("CLS");
				ShortTime();
				break;
			}
			case 5:{//退出程序
				system("CLS");
				Finish_Screen();
				exit(0);
				break;
			default:
				cout << "\n\t\t您输入的序号有误,请重新选择,按任意键继续...";
				getchar();
				getchar();
				system("CLS");
				break; 
			}
		}
	}
	return 0;
}

//******************************************自定义函数******************************************* 
void Start_Screen()
{
	system("color 9");//将字体变为深蓝色 
	
	cout << "\n\n\n";
    cout << "\t\t*************************************************"<<endl;
    cout << "\t\t******                                     ******"<<endl;
    cout << "\t\t******         ★★欢迎进入★★            ******"<<endl;
    cout << "\t\t******                                     ******"<<endl;
    cout << "\t\t******      田径比赛的时间安排系统         ******"<<endl;
    cout << "\t\t******                                     ******"<<endl;
    cout << "\t\t*************************************************"<<endl;
    cout << "\n\n\n";
    cout << "正在为您跳转到主菜单,请稍等...";
    
	Sleep(3000);
    system("CLS");
}

void Finish_Screen()
{
	
	system("color 9");
    cout<<"\n\n\n\n\n";
    cout << "\t\t*************************************************"<<endl;
    cout << "\t\t******                                     ******"<<endl;
    cout << "\t\t******         ★★谢谢使用★★            ******"<<endl;
    cout << "\t\t******                                     ******"<<endl;
    cout << "\t\t******      田径比赛的时间安排系统         ******"<<endl;
    cout << "\t\t******                                     ******"<<endl;
    cout << "\t\t*************************************************"<<endl;
    cout<<"\n\n\n\n\n";
    
}

int Menu()
{
    cout << endl;
    cout << "\t =============================================================================\n";
    cout << "\t||                                                                            ||\n";
    cout << "\t||             ★★★★★★★田径比赛的时间安排系统★★★★★★★             ||\n";
    cout << "\t||                                                                            ||\n";
    cout << "\t||============================================================================||\n";
    cout << "\t||============================================================================||\n";
    cout << "\t||                                                                            ||\n";
    cout << "\t||                          本届田径比赛的项目种类                            ||\n";
    cout << "\t||               [1]110米跑步      [2]100米跑步      [3]跳高                  ||\n";
    cout << "\t||               [4]1000米长跑     [5]800米长跑      [6]110米跨栏             ||\n";
    cout << "\t||               [7]100米跨栏      [8]跳远           [9]铅球                  ||\n";
    cout << "\t||                                                                            ||\n";
    cout << "\t||============================================================================||\n";
    cout << "\t||============================================================================||\n";
    cout << "\t||                                                                            ||\n";
    cout << "\t||                              功能选项卡                                    ||\n";
    cout << "\t||                                                                            ||\n";
	cout << "\t||                       【1】--- 从键盘中输入数据                            ||\n";
    cout << "\t||                       【2】--- 从文件中导入数据                            ||\n";
    cout << "\t||                       【3】--- 输出邻接矩阵                                ||\n";
    cout << "\t||                       【4】--- 输出安排的时间                              ||\n";
    cout << "\t||                       【5】--- 退出程序                                    ||\n";
    cout << "\t||                                                                            ||\n";
    cout << "\t ==============================================================================\n";
    cout << "\t\t\t请输入数字来选择对应的功能:";
    
    int num;
    cin >> num;
    
    return num;
}

void DataFromKeyboard()
{
	cout << endl;
    cout << "\t =============================================================================\n";
    cout << "\t||                                                                            ||\n";
    cout << "\t||             ★★★★★★★你选择的方法是键盘输入★★★★★★★             ||\n";
    cout << "\t||                                                                            ||\n";
    cout << "\t||============================================================================||\n";
    cout << "\t||                                                                            ||\n";
    cout << "\t||                          本届田径比赛的项目种类                            ||\n";
    cout << "\t||               [1]110米跑步      [2]100米跑步      [3]跳高                  ||\n";
    cout << "\t||               [4]1000米长跑     [5]800米长跑      [6]110米跨栏             ||\n";
    cout << "\t||               [7]100米跨栏      [8]跳远           [9]铅球                  ||\n";
    cout << "\t||                                                                            ||\n";
    cout << "\t||============================================================================||\n";
    cout << "\t||                                                                            ||\n";
    cout << "\t||    接下来的每一行是该运动员所参加的所有运动项目序号(每人最多参加三项)    ||\n";
    cout << "\t||                                                                            ||\n";
	cout << "\t||                              以 0 结束输入                                 ||\n";
    cout << "\t||                                                                            ||\n";
	cout << "\t||============================================================================||\n";
	
	while(c != '0')
	{
		c = getchar();
		if(c == '\n')	
		{
			for(j = 0;j < i-1;j ++)
				a[b[j]][b[j+1]] = a[b[j+1]][b[j]] = 1;
			
			if(i==3)
				a[b[0]][b[2]] = a[b[2]][b[0]] = 1;
			
			i = 0;
			cout << "\t\t\t\t\t";
		}
		if(c > '0'&& c <= '9')
			b[i++] = c - 48;
		if(c == '0')
			break;
	}
	
	for(i = 1;i < 10;i ++)
	{
		item = 0;
		for(j = 1;j < 10;j ++)
		{
			if(a[i][j])
				item ++;
		}
		node[i].item = item;
		node[i].number = i;
		node[i].color=0;    //0表示初始化无颜色 
	}
	
		
	cout << "\t||                                                                            ||\n";
    cout << "\t||             ★★★★★★★数据已成功录入★★★★★★★                     ||\n";
    cout << "\t||                                                                            ||\n";
	cout << "\t =============================================================================\n";
	
	flag = true;
	
	//着色
	Draw(1,1);
	
	//按颜色排序
	qsort(node+1,6, sizeof(node[1]), cmp);
	
	cout << "\n\n\n";
    cout << "按任意键继续...";
	getchar();
	getchar();
    system("CLS");
}

void DataFromFile()
{	
	cout << endl;
    cout << "\t =============================================================================\n";
    cout << "\t||                                                                            ||\n";
    cout << "\t||             ★★★★★★★你选择的方法是文件导入★★★★★★★             ||\n";
    cout << "\t||                                                                            ||\n";
    cout << "\t||============================================================================||\n";
    cout << "\t||============================================================================||\n";
	cout << "\t||                                                                            ||\n";
	cout << "\t||                            请确保文件中的格式为                            ||\n";
	cout << "\t||    接下来的每一行是该运动员所参加的所有运动项目序号(每人最多参加三项)    ||\n";
	cout << "\t||                                                                            ||\n";
	cout << "\t||============================================================================||\n";
	cout << "\t||                              是否继续(y或n)                              ||\n";
	cout << "\t||============================================================================||\n";
	char op;//记录用户选择 
	
	re://用户输入错误 
	cout << "\t\t\t\t\t请输入:";
	cin >> op;
	if(op == 'n' || op == 'N')
	{
		cout << "即将返回主菜单,请稍等...";
		Sleep(3500);
		system("CLS");
		return ;
	}
	else if(op == 'y' || op == 'Y') ;
	else
	{
		cout << "\t||                              输入错误重新输入                              ||\n";
		goto re;	
	}
	
	
	char FileName[100];  //文件名
	cout << "\t||============================================================================||\n";
	cout << "\t\t\t\t   请输入文件名称:";
	cin >> FileName; 
	
	cout << "\t||============================================================================||\n";	
	
	f = fopen(FileName,"r");
	c = fgetc(f);

	
	//读取文件并输出
	if((filep=fopen(FileName,"r"))==NULL)
	{
		cout << "\t\t\t打开文件错误!" << endl;
		cout << "\t\t\t即将返回主菜单...";
		Sleep(3500);
		system("CLS");
		return;	
	}
	
	ch = fgetc(filep);
	while(ch!=EOF)
	{
	//	putchar(ch);
		ch = fgetc(filep);
	}
	
	//把文件里的数据录入到矩阵里
	i = 0;
	while(c != EOF) 
	{
		if(c == '\n')	
		{
			for(j = 0;j < i-1;j ++)
				a[b[j]][b[j+1]] = a[b[j+1]][b[j]] = 1;
			
			if(i==3)
				a[b[0]][b[2]] = a[b[2]][b[0]] = 1;
			
			i = 0;
		}
		if(c >= '0'&& c <= '9')
			b[i++] = c - 48;
		
		c = fgetc(f);
	}
	for(i = 1;i < 10;i ++)
	{
		item = 0;
		for(j = 1;j < 10;j ++)
		{
			if(a[i][j])
				item ++;
		}
		node[i].item = item;
		node[i].number = i;
		node[i].color=0;    //0表示初始化无颜色 
	}
	
	cout << "\t||                                                                            ||\n";
    cout << "\t||             ★★★★★★★数据已成功录入★★★★★★★                     ||\n";
    cout << "\t||                                                                            ||\n";
	cout << "\t =============================================================================\n";
	
	flag = true;
	
	//着色
	Draw(1,1);
	
	//按颜色排序
	qsort(node+1,6, sizeof(node[1]), cmp);
	
	cout << "\n\n\n";
    cout << "按任意键继续...";
	getchar();
	getchar();
    system("CLS");
}

int Draw(int k,int color)
{
	bool key;		//表示是否需要着色 
	node[k].color = color;
	
	//对于不相连的顶点着一样的颜色 
	for(j = 1;j < 10;j ++)
	{
		key = true;
		if(!a[k][j] && node[j].color == 0)
		{
			for(i = 1;i < 10;i ++)
			if(a[j][i] && node[i].color == color)
			{
				key = false;
				break;
			}
			if(key) 
				node[j].color=color;
		}
	}
	
	for(i = 1;i < 10;i ++)
		if( !node[i].color )
		{
			Draw( i , color+1);
			break;
		}
	return OK;
}

int cmp(const void *a,const void *b)
{
	struct Node *c = (Node *)a;
	struct Node *d = (Node *)b;
	
	return c->color - d->color;
}

int PrintAdjMatrix()
{
	cout << endl;
    cout << "\t =============================================================================\n";
    cout << "\t||                                                                            ||\n";
    cout << "\t||             ★★★★★★★正在打印邻接矩阵★★★★★★★                   ||\n";
    cout << "\t||                                                                            ||\n";
    cout << "\t||============================================================================||\n";
    cout << "\t||============================================================================||\n";
    cout << "\t||                                                                            ||\n";
    
    for(int i = 1;i < 10;i++){
		printf("\t\t\t\t      ");
	    for(int j = 0;j < 10;j ++){
	    	printf("%d ",a[i][j]);
		}
	    printf("\n\n");
	}
	
	cout << "\t||                                                                            ||\n";	
	cout << "\t =============================================================================\n";
	
	cout << "\n\n\n";
    cout << "按任意键继续...";
	getchar();
	getchar();
    system("CLS");
}

//输出比赛时间安排 
int ShortTime()
{

	cout << endl;
    cout << "\t =============================================================================\n";
    cout << "\t||                                                                            ||\n";
    cout << "\t||            ★★★★★★★本届田径比赛的安排如下★★★★★★★              ||\n";
    cout << "\t||                                                                            ||\n";
    cout << "\t||============================================================================||\n";
    cout << "\t||============================================================================||\n";
    cout << "\t||                                                                            ||\n";
    cout << "\t||               [1]110米跑步      [2]100米跑步      [3]跳高                  ||\n";
    cout << "\t||               [4]1000米长跑     [5]800米长跑      [6]110米跨栏             ||\n";
    cout << "\t||               [7]100米跨栏      [8]跳远           [9]铅球                  ||\n";
    cout << "\t||                                                                            ||\n";
    cout << "\t||============================================================================||\n";
	
	int day = 1; 
	
	printf("\t\t\t第%d天\t%d",day,node[1].number); 
	temp = node[1].color;
	for(i = 2;i<10;i++)      //输出
	{
		if(temp!=node[i].color)
		{
			printf("\n");
			day ++;
			printf("\t\t\t第%d天",day); 
		}
		printf("\t%d ",node[i].number);
		temp = node[i].color;
	}

    cout << "\n\t||                                                                            ||\n";
    cout << "\t =============================================================================\n";
    
    cout << "\n\n\n";
    cout << "按任意键继续...";
	getchar();
	getchar();
    system("CLS");
	return OK;
}
posted @ 2022-07-02 18:52  HeyStar  阅读(1364)  评论(0)    收藏  举报