#include<iostream>
using namespace std;
#include<algorithm>
#include<vector>
#include<functional>
#include<ctime>
#include<numeric>
#include<deque>
#include<map>
#include<fstream> //文件操作
/*常用排序算法
sort //对容器内元素进行排序
random_shuffle //洗牌 指定范围内的元素随机调整此项
merge //容器元素合并 ,并储存到另一容器中
reverse //反转指定范围的元素
*/
/*
sort(iterator beg,iterator end,_Pred) //_Pred谓词 可以从大到小
*/
void myPrint(int val)
{
cout << val << " ";
}
void test_sort_01()
{
vector<int>v;
v.push_back(10);
v.push_back(30);
v.push_back(20);
v.push_back(40);
v.push_back(50);
//利用sort升序
sort(v.begin(), v.end());
for_each(v.begin(), v.end(), myPrint);
cout << endl;
//改变为降序
sort(v.begin(), v.end(),greater<int>());
for_each(v.begin(), v.end(), myPrint);
cout << endl;
}
/*random_shuffle
洗牌 指定范围内的元素随机调整次序
random_shuffle(iterator beg,iterator end);
*/
void test_random_shuffle()
{
srand( (unsigned int)time(NULL) ); //随着时间真实打乱
vector<int>v;
for (int i = 0; i < 10; i++)
{
v.push_back(i);
}
//利用洗牌 算法 打乱顺序 random_shuffle用的时候记得加随机数种子
random_shuffle(v.begin(), v.end());
for_each(v.begin(), v.end(), myPrint);
cout << endl;
}
/*merge 合并的两个容器必须是有序序列! my先sort再merge
两个容器元素合并,并存储到另一容器中
merge(iterator beg1,iterator end1,iterator beg1,iterator end2,iterator dest) //dest目标容器开始迭代器
*/
void test_merge()
{
vector<int>v1;
vector<int>v2;
for (int i = 0; i < 10; i++)
{
v1.push_back(i);
v2.push_back(i+1);
}
vector<int>vTarget;//有数据的容器放到空的容器,目标容器要提前分配内存!!!
vTarget.resize(v1.size() + v2.size());
merge(v1.begin(), v1.end(), v2.begin(), v2.end(), vTarget.begin());
for_each(vTarget.begin(),vTarget.end(),myPrint);
cout << endl;
}
/*reverse
将容器内元素反转
reverse(iterator beg,iterator end)
*/
void test_reverse_01()
{
vector<int>v;
v.push_back(10);
v.push_back(30);
v.push_back(50);
v.push_back(20);
v.push_back(40);
cout<< "反转前" <<endl;
for_each(v.begin(),v.end(),myPrint);
cout<<endl;
reverse(v.begin(), v.end());
cout << "反转后" << endl;
for_each(v.begin(), v.end(), myPrint);
cout << endl;
}
/*常用拷贝和替换算法
copy //容器内指定范围的元素拷贝到另一容器中
replace //将容器指定范围的旧元素改为新元素
replace_if //容器内指定范围且满足条件的元素替换为新元素
swap //互换两个容器的元素
*/
/*copy
容器内指定范围的元素拷贝到另一容器中
copy(iterator beg,iterator end,iterator dest);
按值查找元素,找到返回指定位置迭代器,找不到返回结束迭代器位置
*/
void test_copy_01()
{
vector<int>v1;
for (int i = 0;i < 10;i++)
{
v1.push_back(i);
}
vector<int>v2;
v2.resize(v1.size()); //!!!目标容器提前开辟空间!!!
copy(v1.begin(), v1.end(), v2.begin()); //v2.begin()
for_each(v2.begin(), v2.end(),myPrint);
cout << endl;
}
/*replace
将容器内指定范围的旧元素修改为新元素
replace(iterator beg,iterator end,oldvalue,newvalue);
*/
void test_replace_01()
{
vector<int>v;
v.push_back(20);
v.push_back(30);
v.push_back(50);
v.push_back(30);
v.push_back(40);
v.push_back(20);
v.push_back(10);
v.push_back(20);
cout<< "替换前:" <<endl;
for_each(v.begin(), v.end(), myPrint);
//把20替换成2000
replace(v.begin(),v.end(),20,2000);
cout << "替换后:" << endl;
for_each(v.begin(), v.end(), myPrint);
}
/*replace_if
replace_if(iterator beg,iterator end,_pred,newvalue) //_pred谓词(仿函数) newvalue替换的新元素
*/
class Greater30 {
public:
bool operator() (int val)
{
return val >= 30;
}
};
void test_replace_if_01()
{
vector<int>v;
v.push_back(10);
v.push_back(40);
v.push_back(20);
v.push_back(40);
v.push_back(30);
v.push_back(50);
v.push_back(20);
v.push_back(30);
cout << "替换前:" << endl;
for_each(v.begin(), v.end(), myPrint);
//将大于30的替换成3000
replace_if(v.begin(), v.end(), Greater30(), 3000);
cout << "替换后:" << endl;
for_each(v.begin(), v.end(), myPrint);
cout << endl;
}
/*swap
互换两个容器的元素 (类型要一样)
swap(container c1,container c2);
*/
void test_swap_01()
{
vector<int>v1;
vector<int>v2;
for (int i = 0; i < 10; i++)
{
v1.push_back(i);
v2.push_back(i + 100);
}
cout << "交换前:" << endl;
for_each(v1.begin(), v1.end(), myPrint);
cout << endl;
for_each(v2.begin(), v2.end(), myPrint);
cout << endl;
cout << "-----------------"<<endl;
swap(v1, v2);
cout << "交换后:" << endl;
for_each(v1.begin(), v1.end(), myPrint);
cout << endl;
for_each(v2.begin(), v2.end(), myPrint);
cout << endl;
}
/*常用算术生成算法 头文件#include<numeric> --实用
accumulate //计算容器元素累加总和
fill //向容器中添加元素
*/
/*accumulate
计算区间内 容器元素累加总和
accumulate(iterator beg,iterator end,value); //value为起始值 意思: 起始值 + 函数累加结果
*/
void test_accumulate_01()
{
vector<int>v;
for (int i = 0; i <= 100; i++)
{
v.push_back(i);
}
//参数3,起始累加值
int total = accumulate(v.begin(), v.end(), 0);//不需要起始值就写0
cout<< "total = "<< total <<endl;
}
/*fill
向容器中添加元素
fill(iterator beg,iterator end,value); //value填充的值
*/
void test_fill_01()
{
vector<int>v;
v.resize(10);
//后期重新填充 十个100
fill(v.begin(), v.end(),100);
for_each(v.begin(), v.end(), myPrint);
}
/*常用集合算法
set_intersection //求两个容器的交集
set_union //求两个容器的并集
set_different //求两个容器的差集
*/
/*求两个容器的交集
set_intersection(iterator beg1,iterator end1,iterator beg2,iterator end2,iterator dest);//dest目标容器迭代器
*/
void test_set_intersection_01()
{
vector<int>v1;
vector<int>v2;
for (int i = 0; i < 10; i++)
{
v1.push_back(i); //0~9
v2.push_back(i + 5); //5~14
}
//特殊情况 一个包含另一个 ,目标容器就是小的 ,被包含的那一个 --即子集 所需空间为min( v1.size(),v2.size())
vector<int>vTarget;
vTarget.resize( min( v1.size(),v2.size()) );
//获取交集
vector<int>::iterator itEnd = set_intersection(v1.begin(), v1.end(), v2.begin(), v2.end(), vTarget.begin());
//用itEnd迭代器 用vTarget.end()就会遍历一遍容器元素 ,当交集小于容器size ,剩余位置会用0填充,不准确 ,所以用交集返回的迭代器
for_each(vTarget.begin(), itEnd,myPrint);
cout << endl;
}
/*求两个容器的并集 **注意两个集合必须是有序序列!!! 可以先sort
set_union(iterator beg1,iterator end1,iterator beg2,iterator end2,iterator dest ) //dest为目标迭代器
*/
void test_set_union_01()
{
vector<int>v1;
vector<int>v2;
for (int i = 0; i < 10; i++)
{
v1.push_back(i);
v2.push_back(i + 5);
}
vector<int>vTarget;
//目标容器提前开辟空间
//最特殊的情况,两个容器没有交集,最大所需空间为v1.size() + v2.size()
vTarget.resize(v1.size() + v2.size());
vector<int>::iterator itEnd = set_union(v1.begin(), v1.end(), v2.begin(), v2.end(), vTarget.begin());
for_each(vTarget.begin(), itEnd, myPrint); //考虑打印结果准确,要用itEnd迭代器返回的位置 作为结束位置
cout << endl;
}
/*求两个集合的差集
set_different(iterator beg1,iterator end1,iterator beg2,iterator end2,iterator dest) //dest为目标迭代器
*/
/*差集举例:
v1: 0 1 2 3 4 5 6 7 8 9
v2: 5 6 7 8 9 10 11 12 13 14
v1和v2的差集(属于v1且不属于v2): 0 1 2 3 4 my (v1∩v2)要成为v1的还差的元素集合(关于v1补集 )
v2和v1的差集(属于v2且不属于v1):10 11 12 13 14 my (v1∩v2)要成为v1的还差的元素集合 (关于v2的补集)
*/
void test_set_different_01()
{
vector<int>v1;
vector<int>v2;
for (int i = 0; i < 10; i++)
{
v1.push_back(i);
v2.push_back(i + 5);
}
vector<int>vTarget;
//最特殊,两个不想交差集为本身,所需空间最大为size较大的容器 用algorithm中的 max(v1.size(),v2.size())
vTarget.resize(max(v1.size(),v2.size()));
cout<<"v1和v2的差集为:" <<endl;
vector<int>::iterator itEnd = set_difference(v1.begin(), v1.end(), v2.begin(), v2.end(), vTarget.begin());
for_each(vTarget.begin(), itEnd, myPrint); //考虑打印结果准确,要用itEnd迭代器返回的位置 作为结束位置
cout << endl;
cout << "v2和v1的差集为:" << endl;
itEnd = set_difference(v2.begin(), v2.end(), v1.begin(), v1.end() , vTarget.begin());
for_each(vTarget.begin(), itEnd, myPrint); //考虑打印结果准确,要用itEnd迭代器返回的位置 作为结束位置
cout << endl;
}
//此处为了简洁没有分多个文件进行项目搭建 ,不规范
/*案例-演讲比赛
学校举办一次演讲比赛 ,共有12个人参加,比赛共两轮 ,第一轮为淘汰赛 ,第二轮为决赛
每名选手都有对应的编号 ,如10001~10012
比赛方式:分组比赛,每组6个人
第一轮分为两个小组,整体按照选手编号进行 抽签 后顺序演讲 (序号随机打乱)
十个评委分别给选手打分,去除最高分和最低分,求的平均分为本轮选手的成绩
当小组演讲完成后,淘汰组内排名最低的三位选手,前三名晋级,进入下一轮的比赛
第二轮为决赛,前三名胜出
每轮比赛过后需要显示晋级选手的信息
*/
//功能:
//1.开始演讲比赛
//2.查看往届记录
//3.清空比赛记录
//4.退出比赛程序
//.csv格式文件后缀 可以用Excel打开,也可以用记事本打开
/*打开创建空项目....很细02演讲比赛集
基于STL的演讲比赛流程管理系统
*/
//创建管理类
/*
提供菜单与用户交互
对演讲比赛流程进行控制
与文件的读写交互
*/
#include"speechManager.h";
//构造函数
SpeechManager::SpeechManager()
{
//初始化容器和属性
this->initSpeech();
//创建12名选手
this->createSpeaker();
}
//菜单功能
void SpeechManager::show_Menu()
{
cout << "****************************************" << endl;
cout << "************欢迎参加演讲比赛************" << endl;
cout << "*************1.开始演讲比赛*************" << endl;
cout << "*************2.查看往届记录*************" << endl;
cout << "*************3.清空比赛记录*************" << endl;
cout << "*************0.退出比赛程序*************" << endl;
cout << "****************************************" << endl;
cout << endl;
}
//退出系统
void SpeechManager::exitSystem() //头文件中函数声明,在其他文件中实现时要加作用域!!!
{
cout << "欢迎下次使用" << endl;
system("pause");//按任意键之后退出
exit(0);
}
//创建12名选手
void SpeechManager::createSpeaker()
{
string nameSeed = "ABCDEFGHIJKL";
for (int i = 0; i < 12; i++)
{
string name = "选手";
name += nameSeed[i];
//创建具体选手
Speaker sp;
sp.m_Name = name;
for (int j = 0; j < 2; j++)
{
sp.m_Score[j] = 0;
}
//创建选手编号 并且放入到v1容器中
this->v1.push_back(i + 10001);
//选手编号以及对应选手 放入到map容器中
this->m_Speaker.insert(make_pair(i + 10001, sp));
}
}
//开始比赛 比赛整个流程的控制函数
void SpeechManager::startSpeech()
{
//第一轮开始比赛
//1.抽签
this->speechDraw();
//2.比赛
this->sppechConstest();
//3.显示晋级结果
this->showScore();
//第二轮开始比赛
this->m_index++;
//1.抽签
this->speechDraw();
//2.比赛
this->sppechConstest();
//3.显示最终结果
this->showScore();
//4.保存分数到文件
this->saveRecord(); //冠亚季军 的 编号和得分
cout<<"本届比赛完毕!" <<endl;
system("pause");
system("cls");
//还有读取往届记录...先不做
}
//1.抽签
void SpeechManager::speechDraw()
{
cout<< "第 << " <<this->m_index << " >> 轮比赛选手正在抽签" <<endl;
cout << "------------------------" << endl;
cout << "抽签后演讲顺序如下:" << endl;
if (this->m_index == 1 ) //如果为第一轮
{
//第一轮比赛
random_shuffle(v1.begin(),v1.end()); //打乱
for (vector<int>::iterator it = v1.begin(); it != v1.end(); it++)
{
cout<< *it<< " ";
}
cout << endl;
}
else //第二轮
{
random_shuffle(v2.begin(), v2.end()); //打乱
for (vector<int>::iterator it = v2.begin(); it != v2.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
cout << "------------------------"<<endl;
system("pause");
cout << endl;
}
//比赛
void SpeechManager::sppechConstest()
{
cout << "---------------- 第 << " << this->m_index << " >> 轮比赛正式开始 ---------------" << endl;
//准备临时容器 ,存放小组成绩 虽然几率很低但还是可能重复 ,选用允许重复的容器multimap
multimap<double, int, greater<int>> groupScore;
int num = 0; //记录人员的个数 6人一组
vector<int>v_Src;//选手容器
if (this->m_index == 1)
{
v_Src = v1;
}
else
{
v_Src = v2;
}
//遍历所有选手进行比赛
for (vector<int>::iterator it = v_Src.begin(); it != v_Src.end(); it++)
{
num++;
deque<double>d;
for (int i = 0; i < 10; i++)
{
double score = (rand() % 401 + 600) / 10.f; //600~1000 / 10.f
//cout <<score<<" "; //测试
d.push_back(score);
}
//cout << endl;
sort(d.begin(), d.end(), greater<double>());//排序
d.pop_front(); //去除最高分
d.pop_back(); //去除最低分
double sum = accumulate(d.begin(), d.end(), 0.0f); //总分
double avg = sum / (double)d.size(); //平均分
//打印平均分 测试
//cout << "编号:" << *it << "姓名:" << this->m_Speaker[*it].m_Name << "获取平均分: " << avg <<endl;
//将平均分放到map容器中
this->m_Speaker[*it].m_Score[this->m_index - 1] = avg;
//将打分数据 放入到临时小组容器中
groupScore.insert(make_pair(avg, *it)); //key是选手得分 ,value是具体选手编号 groupScore == 0 ???????????????????????????????????????????????????????
//每6个人取前三名
if (num % 6 == 0) //即6和12时执行 --每组遍历完取一次
{
cout << "第" << num / 6 << "小组名次"<<endl;
for (multimap<double, int, greater<double>>::iterator it = groupScore.begin(); it != groupScore.end(); it++)
{
cout<< "编号: "<< it->second << "姓名: " << this->m_Speaker[it->second].m_Name << "成绩: "
<<this->m_Speaker[it->second].m_Score[this->m_index - 1] << endl;
}
//取走前三名
int count = 0;
for (multimap<double, int, greater<int>>::iterator it = groupScore.begin(); it != groupScore.end() && count < 3; it++,count++)
{
if (this->m_index == 1)
{
v2.push_back((*it).second);
}
else
{
vVictory.push_back((*it).second);
}
}
groupScore.clear(); //每组比完容器内清空,才不会在第二组时把第一组也显示出来 my先取走后清空
cout << endl;
}
}
cout << "--------------------- 第"<< this->m_index <<"轮比赛完毕 ---------------------"<< endl;
system("pause");
}
//显示比赛结果 得分
void SpeechManager::showScore()
{
cout << "--------------------- 第" << this->m_index << "轮选手晋级信息如下:--------------------" << endl;
vector<int>v;
if (this->m_index == 1)
{
v = v2; //第一轮比完,指向v2容器
}
else
{
v = vVictory; //第二轮比完,指向晋级组
}
for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
{
cout<< "选手编号:"<<*it << " 姓名:"<< this->m_Speaker[*it].m_Name << " 得分:"
<< this->m_Speaker[*it].m_Score[this->m_index - 1] <<endl;
}
cout << endl;
system("pause"); //暂停,按任意键后继续
system("cls");
this->show_Menu(); //第二轮时能看到菜单
}
//保存分数到文件
void SpeechManager::saveRecord()
{
ofstream ofs;
ofs.open("speech.csv", ios::out | ios::app); //用追加的方式写文件
//将每个选手数据 写入到文件中
for (vector<int>::iterator it = vVictory.begin(); it != vVictory.end(); it++)
{
ofs << *it << "," << this->m_Speaker[*it].m_Score[1] <<",";
}
ofs << endl;
ofs.close();
cout<< "记录已经保存" <<endl;
}
//析构函数
SpeechManager::~SpeechManager()
{
}
void SpeechManager::initSpeech()
{
//容器都置空
this->v1.clear();
this->v2.clear();
this->vVictory.clear();
this->m_Speaker.clear();
//初始化轮数
this->m_index = 1;
}
void test_sppech_main()
{
//创建管理对象
SpeechManager sm;
/*
//测试12名选手创建
for (map<int, Speaker>::iterator it = sm.m_Speaker.begin(); it != sm.m_Speaker.end(); it++)
{//map<first,second>
cout<< "选手编号: "<< it->first << " 姓名 " << it->second.m_Name << " 分数:"<< it->second.m_Score <<endl;
}
*/
int choice = 0;//用于存储用户的输入
while (true)
{
sm.show_Menu();
cout<< "请输入您的选择: " <<endl;
cin >> choice; //接受用户的选择
switch (choice)
{
case 1:
sm.startSpeech();
break;
case 2:
break;
case 3:
break;
case 0:
sm.exitSystem();
break;
default:
system("cls"); //清屏
break;
}
}
}
int main()
{
//cout<< <<endl;
test_sppech_main();
return 0;
}
头文件 speaker.h
#pragma once
#include<iostream>;
using namespace std;
class Speaker
{
public:
string m_Name; //姓名
double m_Score[2]; //分数 最多两轮得分 第二轮存放数组第二位
};
头文件 speechManager.h
#pragma once
#include<iostream>
using namespace std;
#include<vector>
#include<map>
#include"speaker.h"
//设计演讲类
class SpeechManager {
public:
//构造函数
SpeechManager();
//菜单功能
void show_Menu();
//退出系统
void exitSystem();
//析构函数
~SpeechManager();
//初始化容器和属性
void initSpeech();
//创建12名选手
void createSpeaker();
//成员属性
//保存第一轮比赛选手编号容器
vector<int>v1;
//第一轮晋级选手编号
vector<int>v2;
//胜出前三名选手编号容器
vector<int>vVictory;
//存放编号以及对应具体选手容器
map<int,Speaker>m_Speaker;
//存放比赛轮数
int m_index;
};
保存记录后在目录下生成文件.csv 可以用Excel或记事本查看 :
第一轮比赛:
第二轮比赛(决赛):
保存记录: