数据结构课设:中国计算机设计大赛赛事统计

目录

一、项目介绍

二、问题描述

2.1、问题1:

2.2、问题分析

2.2.1需求分析:

2.2.2要求:

2.2.3容器的选择:

2.2.3涉及的知识:

2.3概要设计

2.3.1结构体的定义

2.3.2定义不同的函数

2.4结果展示

2.4.1输入参赛队伍基本信息并存储

 2.4.2选择进行的操作——删除,添加及修改

3.1、问题2:

3.2、问题分析

3.2.1需求分析:

3.2.3涉及的知识:

3.3概要设计

3.3.1创建二叉排序树,插入结点及查找操作

3.3.2计算ASL

3.3.3从文档team.txt读取文本信息

3..4.4根据队伍编号查找信息

3.4结果展示

3.4.1从team.txt读取文档并输出

 3.4.2在文件中添加队伍基本信息

3.4.5通过编号查找队伍信息并输出

 4.1、问题4:

4.1.1需求分析

4.1.2概要设计

4.1.3结果展示

5.1.1需求分析

5.1.2概要设计

5.1.3算法介绍

5.1.4参考代码



一、项目介绍

本次课程设计要求协助中国大学生计算机设计大赛江苏省组委会,设计一款赛事管理系统,实现赛务相关的数据管理及信息服务

该系统能够为省级赛事管理解决以下问题:

(1)能够管理各参赛队的基本信息(包含参赛队编号,参赛作品名称,参赛学校,赛事类别,参赛者,指导老师),赛事类别共11项(参见大赛官网jsjds.blcu.edu.cn);包括增加、删除、修改参赛队伍的信息。

(2)从team.txt中读取参赛队伍的基本信息,实现基于二叉排序树的查找。根据提示输入参赛队编号,若查找成功,输出该赛事类别对应的基本信息(参赛作品名称、参赛学校、赛事类别、参赛者和指导老师信息),同时,输出查找成功时的平均查找长度ASL;否则,输出“查找失败!”。

(3)能够提供按参赛学校查询参赛团队(或根据赛事类别查询参赛团队),即,根据提示输入参赛学校名称(赛事类别),若查找成功,输出该学校参赛的(该赛事类别的)所有团队的基本信息,输出的参赛团队按赛事类别有序输出。(排序算法可从选择排序、插入排序、希尔排序、归并排序、堆排序中任意选择,并为选择算法的原因做出说明。)

(4)为省赛现场设计一个决赛叫号系统。所有参赛队按赛事组织文件中的赛事类别分到9个决赛室,决赛室按顺序叫号,被叫号参赛队进场,比赛结束后,下一参赛队才能进赛场。请模拟决赛叫号系统,演示省赛现场各决赛室的参赛队进场情况。(模拟时,要能直观展示叫号顺序与进场秩序一致)

(5)赛事系统为参赛者提供赛地的校园导游程序,为参赛者提供各种路径导航的查询服务。以我校长山校区提供比赛场地为例,(请为参赛者提供不少于10个目标地的导航。可为参赛者提供校园地图中任意目标地(建筑物)相关信息的查询;提供任意两个目标地(建筑物)的导航查询,即查询任意两个目的地(建筑物)之间的一条最短路径。

二、问题描述

2.1、问题1:

管理各参赛队的基本信息(包含参赛队编号,参赛作品名称,参赛学校,赛事类别,参赛者,指导老师),赛事类别共11项;包括增加、删除、修改参赛队伍的信息。

2.2、问题分析

2.2.1需求分析:

存储输入参赛队伍的基本信息,其中包括对结点数据的查找,并进行增加,删除,并对信息进行修改。

2.2.2要求:

规定每个参赛队必须有一个唯一的编号,以避免重复命名;规定参赛作品的名称必须是唯一的,以避免同名的作品混淆设置两个结构体,学校的结构体与比赛项目的结构体;

2.2.3容器的选择:

采用vector容器,可以实现动态数组而产生的容器,vector也是一种顺序容器,在内存中连续排列,因此可以通过下标快速访问,时间复杂度为O(1)。连续排列也意味着大小固定,数据超过vector的预定值时vector将自动扩容。

2.2.3涉及的知识:

利用std::getline() 函数从标准输入流 std::cin 中动态获取用户输入,并将其存储到相应的变量中,然后用这些变量初始化一个新的 Team 结构体,并将其添加到向量 teams 中,vector容器中内置函数的用法。

2.3概要设计

2.3.1结构体的定义

struct Team {
    int id;//参赛编号
    string name;//参赛作品名称
    string school;//参赛学校
    string category;//赛事类别
    vector<string> members;//参赛成员
    string coach;//指导老师

   //构造函数
    Team(int id, string name, string school, string category,
        vector<string> members, string coach) :
        id(id), name(name), school(school), category(category),
        members(members), coach(coach) {};
}

2.3.2定义不同的函数

实现对各参赛基本信息的管理及增添,修改,删除等操作

//增添参赛队伍信息
void add_team(vector<Team>& teams, int& team_id);
//删除参赛队伍信息
void remove_team(vector<Team>& teams) ;
//修改参赛队伍信息信息
void modify_team(vector<Team>& teams) 

2.4结果展示

2.4.1输入参赛队伍基本信息并存储

 2.4.2选择进行的操作——删除,添加及修改

 

3.1、问题2:

从team.txt中读取参赛队伍的基本信息,实现基于二叉排序树的查找。根据提示输入参赛队编号,若查找成功,输出该赛事类别对应的基本信息(参赛作品名称、参赛学校、赛事类别、参赛者和指导老师信息),同时,输出查找成功时的平均查找长度ASL;否则,输出“查找失败!”。

3.2、问题分析

3.2.1需求分析:

从team.txt中读取基本信息,并实现基于二叉树排序树的查找,若查找成功则输出对应的基本信息,同时计算平均查找长度ASL;否则查找失败

3.2.3涉及的知识:

iostream包含输入输出流,fstream包含文件读写相关函数,string包含字符串相关操作函数,iomanip用来设置输出格式。

3.3概要设计

3.3.1创建二叉排序树,插入结点及查找操作

// 二叉排序树节点类
struct BinaryTreeNode {
    Team data;
    BinaryTreeNode* lchild, * rchild;
    BinaryTreeNode(Team x):data(x), lchild(NULL), rchild(NULL) {}
};

// 插入节点到二叉排序树
BinaryTreeNode* insert(BinaryTreeNode* root, Team data)

// 查找二叉排序树节点
BinaryTreeNode* search(BinaryTreeNode* root, string team_id)

3.3.2计算ASL

// 计算节点的ASL
void get_asl(int depth, int& node_num, int& path_length_sum, BinaryTreeNode* root) {
    if (root == NULL) return;
    node_num++;
    path_length_sum += depth;
    get_asl(depth + 1, node_num, path_length_sum, root->lchild);
    get_asl(depth + 1, node_num, path_length_sum, root->rchild);
}

3.3.3从文档team.txt读取文本信息

// 去除字符串中的空格和换行符
void Remove(string& s) {
    int index = 0;
    if (!s.empty()) {
        while ((index = s.find('\t', index)) != string::npos) {
            s.erase(index, 1);
        }
        index = 0;
        while ((index = s.find('\n', index)) != string::npos) {
            s.erase(index, 1);
        }
        index = 0;
        while ((index = s.find('\r', index)) != string::npos) {
            s.erase(index, 1);
        }
    }
}

// 从文件读取参赛队伍信息
void Read() {
    int x = 0;
    ifstream i;
    i.open("team.txt");
    string Temp;
    while (getline(i, Temp)) {
        Remove(Temp);
        for (int j = 0; j < 6; j++) {
            int Position = Temp.find('#');
            string s = Temp.substr(0, Position);
            Temp = Temp.substr(Position + 1);
            if (j == 0) {
                node[x].id = s;
            }
            else if (j == 1) {
                node[x].name = s;
            }
            else if (j == 2) {
                node[x].school = s;
            }
            else if (j == 3) {
                node[x].category = s;
            }
            else if (j == 4) {
                node[x].members = s;
            }
            else if (j == 5) {
                node[x].coach = s;
            }
        }
        x++;
    }
    i.close();
}

3..4.4根据队伍编号查找信息

// 根据队伍编号在数组node[]中查找对应的队伍信息
// 若查找成功,返回该队伍在数组中的下标;查找失败,返回-1。
int Search(string id) {
    for (int i = 0; i < 10000; i++) {
        if (node[i].id == id) {
            return i;
        }
    }
    return -1;
}

// 查找队伍信息并输出和计算ASL
void Find() {
    string id;
    cout << "请输入要查找的队伍编号:" << endl;
    cin >> id;

    int index = Search(id);
    if (index == -1) {
        cout << "查找失败!未找到对应队伍。" << endl << endl;
        return;
    }

    // 查找成功,输出队伍基本信息,并计算并输出该队伍的ASL
    cout << "队伍基本信息:" << endl;
    cout << "参赛队伍编号: " << node[index].id << endl;
    cout << "参赛作品名称: " << node[index].name << endl;
    cout << "所属学校: " << node[index].school << endl;
    cout << "赛事类别: " << node[index].category << endl;
    cout << "参赛者信息: " << node[index].members << endl;
    cout << "指导老师信息: " << node[index].coach << endl;
    Output(index);
    cout << "ASL: " << ASL(index) << endl << endl;
}

3.4结果展示

3.4.1从team.txt读取文档并输出

 3.4.2在文件中添加队伍基本信息

3.4.5通过编号查找队伍信息并输出

 4.1、问题4:

4.1.1需求分析

读取文件并提取参赛编号及赛事类别,根据赛事类别将参赛队伍分到9个参赛室中,并将参赛队伍存放在参赛室中,打印叫号的结果,叫号完毕后,输出进场情况

4.1.2概要设计

   // 初始化决赛室
    vector<FinalRoom> finalRooms = InitializeFinalRooms();

    // 从文件读取参赛队伍信息
    vector<Team> teams = ReadTeamsFromFile();

    // 叫号并进场
    CallAndEnter(finalRooms, teams);

    // 打印决赛室的参赛队进场情况
    PrintFinalRooms(finalRooms);

    // 决赛室叫号功能
    while (true) {
        int roomNumber;
        string teamId;

        cout << "请输入决赛室号码和选手编号(输入0退出):";
        cin >> roomNumber;

        // 输入为0时退出循环
        if (roomNumber == 0) {
            break;
        }

        cin >> teamId;

        // 决赛室叫号
        CallTeamInFinalRoom(finalRooms, roomNumber, teamId);
    }

4.1.3结果展示

5.1.1需求分析

设计一个江科大校园导游系统,为来访的客人提供各种信息查询服务,如查询景点信息,找到最短路径

任务定义

设置景点,路径相关信息,构成无向图;提供景点相关信息查询;提供问路查询,找到最短路径

5.1.2概要设计

设置一个结构体包含景点名称和介绍,再设置一个MGraph,含实现功能的函数

Seek(int i)函数查询景点名称以及介绍,使用Floyd()算出最短路径并且输出,Allpaths()输出所有的路径信息,Printshortpath()输出两个景点的最短路径,void meau()展示功能菜单栏选择想要执行的功能

5.1.3算法介绍

弗洛伊德算法,也称为 Floyd-Warshall 算法,是一种动态规划算法,用于解决所有点对之间的最短路径问题。该算法基于递推和分治的思想,可以在 O(n^{3})O(n3) 的时间复杂度内计算出所有点对之间的最短路径。

  1. 初始化一个二维数组 dist,用于存储任意两个顶点之间的最短路径长度;
  2. 对于每对顶点 (i,j)(i,j),如果存在一条边连接顶点 ii 和 jj,则将 dist[i][j] 初始化为这条边的权值;否则,将 dist[i][j] 初始化为一个较大的数(比如 INF);
  3. 对于每个中间节点 kk,依次更新所有顶点对之间的距离,更新方式为:如果顶点对 (i,j)(i,j) 不经过中间节点 kk 的话,则它们之间的距离 dist[i][j] 不需要更新;否则,它们之间的距离应该为经过中间节点 kk 后的距离 dist[i][k] + dist[k][j],如果 dist[i][j] 大于该值,则更新 dist[i][j] 为该值。
  4. 完成上述更新后,返回 dist 数组即可。

5.1.4参考代码

//使用弗洛伊德算法求解最短路径
void MGraph::Floyd()
{
	for (int i = 0; i<vertexNum; i++)           //初始化dist和path 
		for (int j = 0; j<vertexNum; j++)
	{
		dist[i][j] = arc[i][j];
		if (dist[i][j] != 10000)
			path[i][j] = a[i].code + a[j].code;
		else path[i][j] = " ";
	}
	for (int k = 0; k<vertexNum; k++)                      //判定顶点i j之间是否经过k
		for (int i = 0; i<vertexNum; i++)
			for (int j = 0; j<vertexNum; j++)
	if (dist[i][k] + dist[k][j]<dist[i][j])
	{
		dist[i][j] = dist[i][k] + dist[k][j];
		path[i][j] = path[i][k] + "-" + path[k][j];
	}
}
void MGraph::Allpathlengths()
{
	cout << "图的所有路径长如下:" << endl;
	for (int i = 0; i < vertexNum; i++)  //输出图的各边长信息
	{
		for (int j = 0; j < vertexNum; j++)
			if (dist[i][j] == 10000)
				cout << " ";
			else
				cout << setw(2) << setiosflags(ios::left) << dist[i][j] << " ";//3个字符位置,且左对齐
		cout << endl;
	}
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值