数据结构课设

一.问题定义

 

本次课程设计要求协助中国大学生计算机设计大赛江苏省组委会,设计一款赛事管理系统,实现赛务相关的数据管理及信息服务,该系统能够为省级赛事管理解决以下问题:

2.问题分析

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

(2)从team.txt中读取参赛队伍的基本信息,实现基于二叉排序树的查找。根据提示输入参赛队编号,若查找成功,输出该赛事类别对应的基本信息(参赛作品名称、参赛学校、赛事类别、参赛者和指导老师信息),同时,输出查找成功时的平均查找长度ASL;否则,输出“查找失败!”。
(3)能够提供按参赛学校查询参赛团队(或根据赛事类别查询参赛团队),即,根据提示输入参赛学校名称(赛事类别),若查找成功,输出该学校参赛的(该赛事类别的)所有团队的基本信息,输出的参赛团队按赛事类别有序输出。(排序算法可从选择排序、插入排序、希尔排序、归并排序、堆排序中任意选择,并为选择算法的原因做出说明。)

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

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

3.课程设计

(1)参赛队基本信息用结构体(S)表示,包含参赛队编号,参赛作品名称,参赛学校,赛事类别,参赛者和指导老师。

struct Team {
    string id;// 参赛队编号
    string name; // 参赛作品名称
    string school; // 参赛学校
    string category; // 赛事类别
    string members; // 参赛者
    string coach; // 指导老师
};

(2)新增参赛队伍

// 新增参赛队伍
void Event::addTeam(const string& id, const string& name, const string& school, const string& category, const string& member, const string& coach) {
    teams.push_back(Team{ id, name, school, category, member, coach }); // 将新的参赛队伍信息添加到队伍列表中
}

(3)删除参赛队伍的信息

//删除参赛队伍的信息
void Event::removeTeam(string id) {
    // 使用STL算法查找要删除的参赛队伍
    auto it = find_if(teams.begin(), teams.end(), [&](const Team& t) { return t.id == id; });
    if (it != teams.end()) {
        // 从队列中删除该参赛队伍
        teams.erase(it);   
    }
    
}

(4)修改参赛队伍的信息

//修改参赛队伍的信息
void Event::updateTeam(const string& id, const string& name, const string& school, const string& category, const string& member, const string& coach) {
    // 使用STL算法查找要修改的参赛队伍
    auto it = find_if(teams.begin(), teams.end(), [&](const Team& t) { return t.id == id; });
    if (it != teams.end()) {
        // 修改参赛队伍信息
        it->name = name;
        it->school = school;
        it->category = category;
        it->member = member;
        it->coach = coach;
    }
}

(5)将队列中的队伍信息写入到文件中


void Event::saveToFile(const string& filename) {
    ofstream outfile(filename);
    if (outfile) {
        for (const auto& team : teams) {
            outfile << team.id << "#" << team.name << "#" << team.school << "#" << team.category << "#" << team.member << "#" << team.coach << endl;
        }
        cout << "保存成功!" << endl;
    }
    else {
        cout << "保存文件 " << filename << " 失败!" << endl;
    }
}

 

实现将队列的队伍信息写入到文件中,调用saveToFile()函数将更新后的信息写回文件中,这样就可以直接在team.txt文件中查看到更新后的参赛队伍信息了。

(6)二叉排序树查找参赛队伍的信息

二叉排序树(Binary Search Tree,BST)是一种特殊的二叉树,它具有以下性质:

1. 若左子树非空,则左子树上所有节点的值均小于根节点的值;

2. 若右子树非空,则右子树上所有节点的值均大于根节点的值;

3. 左右子树也分别为二叉排序树;

4. 没有键值相等的节点。

由于二叉排序树具有上述性质,我们可以利用它进行非常高效的查找、插入和删除操作。例如,对于一个有n个节点的二叉排序树,在平均和最坏情况下,查找、插入和删除操作的时间复杂度都为 O(log n)。
 

void BST::searchHelper(TeamNode* current, string id, int depth) {
    if (current == nullptr) {
        cout << "查找失败!" << endl;
        return;
    }
 
    if (id == current->id) {
        cout << "基本信息:" << endl;
        cout << "作品名称:" << current->name << endl;
        cout << "参赛学校:" << current->school << endl;
        cout << "赛事类别:" << current->category << endl;
        cout << "参赛者:" << current->member << endl;
        cout << "指导老师:" << current->coach << endl;
        cout << "平均查找长度ASL:" << avgSearchLen() << endl;
        return;
    }
    else if (id < current->id) {
        searchHelper(current->left, id, depth + 1);
    }
    else {
        searchHelper(current->right, id, depth + 1);
    }
}

插入操作:将新节点插入二叉排序树的过程,需要从根节点出发,比较要插入节点的键值与当前节点的键值的大小关系,依次向左或右子树递归,直到空节点位置。
删除操作:删除指定节点的过程,需要涉及改变英文二叉树的结构,涉及两个场景:要删除的节点没有子节点和要删除的节点有一个子节点,或者要删除的节点有两个子节点。
查找操作:从根节点开始遍历BST,与当前节点的值进行比较大小,递归查找到要查找的节点。

(7)利用Dijkstra设计最短路径

void merge(vector<Team>& Teams, int l, int mid, int r) {
    // 合并两个有序数组
    vector<Team> tmp(r - l + 1);
    int i = l, j = mid + 1, k = 0;

    while (i <= mid && j <= r) {
        if (Teams[i].id < Teams[j].id) {
            tmp[k++] = Teams[i++];
        }
        else {
            tmp[k++] = Teams[j++];
        }
    }

    while (i <= mid) {
        tmp[k++] = Teams[i++];
    }
    while (j <= r) {
        tmp[k++] = Teams[j++];
    }

    for (int p = 0; p < k; p++) {
        Teams[l + p] = tmp[p];
    }
}

void merge_sort(vector<Team>& Teams, int l, int r) {
    // 归并排序的递归实现
    if (l >= r) {
        return;
    }

    int mid = l + (r - l) / 2;
    merge_sort(Teams, l, mid);
    merge_sort(Teams, mid + 1, r);
    merge(Teams, l, mid, r);
}

void sort_teams(vector<Team>& Teams) {
    // 调用归并排序对 team vector 进行排序
    merge_sort(Teams, 0, Teams.size() - 1);
}
这是归并排序的

 利用算法可以将江科大地图设计成下面 这个样子,利用Dijkstra算法可以实现查找最短路径。

(8)归并排序

void merge(vector<Team>& Teams, int l, int mid, int r) {
    // 合并两个有序数组
    vector<Team> tmp(r - l + 1);
    int i = l, j = mid + 1, k = 0;

    while (i <= mid && j <= r) {
        if (Teams[i].id < Teams[j].id) {
            tmp[k++] = Teams[i++];
        }
        else {
            tmp[k++] = Teams[j++];
        }
    }

    while (i <= mid) {
        tmp[k++] = Teams[i++];
    }
    while (j <= r) {
        tmp[k++] = Teams[j++];
    }

    for (int p = 0; p < k; p++) {
        Teams[l + p] = tmp[p];
    }
}

void merge_sort(vector<Team>& Teams, int l, int r) {
    // 归并排序的递归实现
    if (l >= r) {
        return;
    }

    int mid = l + (r - l) / 2;
    merge_sort(Teams, l, mid);
    merge_sort(Teams, mid + 1, r);
    merge(Teams, l, mid, r);
}

void sort_teams(vector<Team>& Teams) {
    // 调用归并排序对 team vector 进行排序
    merge_sort(Teams, 0, Teams.size() - 1);
}
这是归并排序的

 

 

 

 

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值