C++系统学习(算法和案例)

#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或记事本查看  :

 

第一轮比赛:

 第二轮比赛(决赛):

保存记录: 

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值