【数据结构与算法课程设计】运动比赛的时间安排问题
设计目的
《数据结构》课程主要介绍最常用的数据结构,阐明各种数据结构内在的逻辑关系,讨论其在计算机中的存储表示,以及在其上进行各种运算时的实现算法,并对算法的效率进行简单的分析和讨论。进行数据结构课程设计要达到以下目的:
- 了解并掌握数据结构与算法的设计方法,具备初步的独立分析和设计能力;
- 初步掌握软件开发过程的问题分析、系统设计、程序编码、测试等基本方法和技能;
- 提高综合运用所学的理论知识和方法独立分析和解决问题的能力;
- 训练用系统的观点和软件开发一般规范进行软件开发,培养软件工作者所应具备的科学的工作方法和作风。
任务概述
设某田径比赛共有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所示:

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

图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所示:

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

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

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

图 4 - 6 Draw()函数N-S图
程序运行数据及其结果
开始界面,菜单界面,结束界面展示:
本程序的开始界面如图5-1所示,菜单界面如图5-2所示,结束界面如图5-3所示。

图 5 - 1开始界面

图 5 - 2菜单界面

图 5 - 2结束界面
从键盘输入数据
输入的数据为:
6 5 1
2 6
4 3 6
2 4 7
9 2 6
3 6
输入数据的截图如图5-4所示,该数据的邻接矩阵如图5-5所示,该数据安排的时间如图5-6所示。

图 5 - 4输入数据

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

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

图 5 - 7数据在文件中的格式

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

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

图 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;
}

浙公网安备 33010602011771号