目录
一、实验内容
二、实验过程
1.撰写自己的算法和函数,结合容器和迭代器解决序列变换(如取反、平方、立方),像素变换(二值化、灰度拉伸)
1.1 非模板函数实现
?1.2 模板函数实现?
?1.3使用sort函数实现
2.用set存储学生信息,并进行增删改查操作
?2.1 set存储?
2.2 vector存储
3.输入一个字符串,用map统计每个字符出现的次数并输出字符及对应的次数
一、实验内容
1.撰写自己的算法和函数,结合容器和迭代器解决序列变换(如取反、平方、立方),像素变换(二值化、灰度拉伸);
2.用set存储学生信息,并进行增删改查操作;
3.输入一个字符串,用map统计每个字符出现的次数并输出字符及对应的次数。
二、实验过程
1.撰写自己的算法和函数,结合容器和迭代器解决序列变换(如取反、平方、立方),像素变换(二值化、灰度拉伸)
1.1 非模板函数实现
就是使用最普通的方法对元素进行取反、平方和立方操作。
实现代码:
void transInvT(T a[],T b[],int nNum) //对元素取反
{
for(int i=0;i<nNum;i++)
{
b[i] = -a[i];
}
}
void transSqrT(T a[],T b[],int nNum) //对元素求平方
{
for(int i=0;i<nNum;i++)
{
b[i] = a[i]*a[i];
}
}
void transPow(T a[],T b[],int nNum) //对元素求立方
{
for(int i=0;i<nNum;i++)
{
b[i] = a[i]*a[i]*a[i];
}
}
void TestTrans()
{
const int N=5;
int a[N] = {2,4,6,8,10};
outputCont("a",cout,a,a+N);
int b[N];
vector<double> vb(N);
transInv(a,b,N);
outputCont("Inv a",cout,b,b+N);
transSqr(a,b,N);
outputCont("Sqr a",cout,b,b+N);
transPow(a,b,N);
outputCont("Pow a",cout,b,b+N);
transInvT(a,b,N);
}
运行结果:
?1.2 模板函数实现?
模板函数这方面可以看我上次发的关于模板函数的博客。C++ 模板类与智能指针
实现代码:
template <typename T>
void transInvT(T a[],T b[],int nNum) //对元素取反
{
for(int i=0;i<nNum;i++)
{
b[i] = -a[i];
}
}
template <typename T>
void transSqrT(T a[],T b[],int nNum) //对元素求平方
{
for(int i=0;i<nNum;i++)
{
b[i] = a[i]*a[i];
}
}
template <typename T>
void transPow(T a[],T b[],int nNum) //对元素求立方
{
for(int i=0;i<nNum;i++)
{
b[i] = a[i]*a[i]*a[i];
}
}
template<typename T>
T InvT(T a)
{
return -a;
}
template<typename T>
class MyThreshold
{
public:
int _nThreshold;
MyThreshold(int n=128):_nThreshold(n){}
int operator()(T val)
{
return val<_nThreshold?0:1; //小于_nThreshold返回0
}
};
template <typename inputIter,typename outputIter,typename MyOperator>
void transInvT(inputIter begInput,inputIter endInput,outputIter begOutput,MyOperator op) //对元素取反
{
for(;begInput!=endInput;begInput++,begOutput++)
{
//*begOutput = -(*begInput);
*(begOutput) = op(*begInput);
}
}
template <typename T>
void outputCont(string strName,ostream& os,T begin,T end) //输出元素
{
os<<strName<<":";
for(;begin!=end;begin++)
{
os<<*begin<<"\t";
}
os<<endl;
}
void TestTrans()
{
const int N=5;
int a[N] = {2,4,6,8,10};
outputCont("a",cout,a,a+N);
int b[N];
vector<double> vb(N);
transInv(a,b,N);
outputCont("Inv a",cout,b,b+N);
transSqr(a,b,N);
outputCont("Sqr a",cout,b,b+N);
transPow(a,b,N);
outputCont("Pow a",cout,b,b+N);
transInvT(a,b,N);
outputCont("InvT a",cout,b,b+N);
transSqrT(a,b,N);
outputCont("SqrT a",cout,b,b+N);
transInvT(a,a+N,b,InvT<int>);
outputCont("InvT a",cout,b,b+N);
transInvT(a,a+N,vb.begin(),InvT<int>); //将取反的结果存入容器vb
outputCont("Inv a by iter",cout,vb.begin(),vb.end()); //从容器中输出结果
//查看一组数据中有几个是小于2的,可用作图像二值化处理,根据阈值将像素分为两个部分
transInvT(a,a+N,vb.begin(),MyThreshold<int>(2));
outputCont("Inv a by treshold",cout,vb.begin(),vb.end());
}
运行结果:
?1.3使用sort函数实现
sort函数用于C++中,对给定区间所有元素进行排序,默认为升序,也可进行降序排序。sort函数进行排序的时间复杂度为n*log2n,比冒泡之类的排序算法效率要高,sort函数包含在头文件为#include<algorithm>的c++标准库中。
语法
Sort(start,end,cmp)
参数
(1)start表示要排序数组的起始地址;
(2)end表示数组结束地址的下一位;
(3)cmp用于规定排序的方法,可不填,默认升序。
实现代码:
void TestSort()
{
const int N = 5;
int c[N] = {8,4,10,2,6};
outputCont("array c",cout,c,c+N);
sort(c,c+N); //默认是按照升序排序
outputCont("default sorted",cout,c,c+N);
//sort函数包含在#include <algorithm>的标准库中,sort()函数有三个参数,依次为要排序数据的起始地址,结束地址,排序的方法
sort(c,c+N,mycoup<int>); //将用于比较的模板函数作用第三个参数,指定排序方式,使其按照降序排列
outputCont("mycoup sorted",cout,c,c+N);
//标准库模板类,在#include <functional>库里面,表示内置类型从大到小排序,less表示从小到大排序
sort(c,c+N,greater<int>());
outputCont("greater sorted",cout,c,c+N);
sort(c,c+N,less<int>());
outputCont("less sorted",cout,c,c+N);
sort(c,c+N,MyCompC<int>()); //自定义模板类
outputCont("MyCompC sorted",cout,c,c+N);
}
运行结果:
2.用set存储学生信息,并进行增删改查操作
set是STL中一种标准关联容器。它底层使用平衡的搜索树——红黑树实现,插入删除操作时仅仅需要指针操作节点即可完成,不涉及到内存移动和拷贝,所以效率比较高。set,顾名思义是“集合”的意思,在set中元素都是唯一的,而且默认情况下会对元素自动进行升序排列,支持集合的交(set_intersection),差(set_difference) 并(set_union),对称差(set_symmetric_difference) 等一些集合上的操作,如果需要集合中的元素允许重复那么可以使用multiset。
?2.1 set存储?
实现代码:
void TestSet()
{
vector<studentInfo> students;
students.push_back(studentInfo("10021","Zhang san"));
students.push_back(studentInfo("10002","Li si"));
students.push_back(studentInfo("10003","Wang wu"));
students.push_back(studentInfo("10011","Wang Liu"));
students.push_back(studentInfo("10010","Wu Liu"));
students.push_back(studentInfo("10003","Wang wu"));
students.push_back(studentInfo("10002","Li si"));
set<studentInfo> studentSet(students.begin(),students.end());
outputCont("student set",cout,studentSet.begin(),studentSet.end());
//增加三个元素,插入value,返回pair配对对象
studentSet.insert(studentInfo("10022","Xiao ming"));
studentSet.insert(studentInfo("10005","Xiao li"));
studentSet.insert(studentInfo("10053","Xiao xie"));
outputCont("insert after",cout,studentSet.begin(),studentSet.end());
//insert()函数返回值是pair<set<int>::iterator,bool>,bool标志着插入是否成功(使用时用second表示返回值的第二个位置),
//而iterator代表插入的位置(用first表示第一个位置),若key_value已经在set中,则iterator表示的key_value在set中的位置。
//根据.second判断是否插入成功(注:value不能与set容器内元素重复)
cout<<"insert(10006,Xiao ren).second = ";
if(studentSet.insert(studentInfo("10006","Xiao ren")).second)
{
cout<<"insert success"<<endl;
outputCont("insert studentset",cout,studentSet.begin(),studentSet.end());
}
else
cout<<"insert false"<<endl;
//删除元素
//方式1:移除set容器内元素值为value的所有元素
studentSet.erase(studentInfo("10022","Xiao ming"));
outputCont("first erase after",cout,studentSet.begin(),studentSet.end());
//方式2:移除pos位置的元素,无返回值
set<studentInfo>::iterator iter = studentSet.begin();
studentSet.erase(iter);
outputCont("second erase after",cout,studentSet.begin(),studentSet.end());
//修改元素的值
for(set<studentInfo>::iterator it = studentSet.begin();it!=studentSet.end();it++)
{
if((it->_strNo)=="10005")
{
studentSet.erase(studentInfo("10005","Xiao li"));
studentSet.insert(studentInfo("10005","Xxx"));
}
}
outputCont("revise after",cout,studentSet.begin(),studentSet.end());
//查找元素
//方式1:count(value)返回set对象内元素值为value的元素个数
cout<<"10010,Wu Liu is count: "<<studentSet.count(studentInfo("10010","Wu Liu"))<<endl;
//方式2:find(value)返回value所在位置,找不到则返回end()
//find会挨个查找set,查找成功返回一个指向指定元素的迭代器,找不到则返回end()
cout<<"find (10010,Wu Liu):";
if(studentSet.find(studentInfo("10010","Wu Liu"))!=studentSet.end())
{
cout<<"find it"<<endl;
}
//清空set
studentSet.clear();
if(studentSet.empty())
{
cout<<"studentSet is NULL"<<endl;
}
}
运行结果:
?在一开始给了重复的数据只出现一个,且它会自动排序,证明了在set中元素都是唯一的,而且默认情况下会对元素自动进行升序排列。
2.2 vector存储
向量(Vector)是一个封装了动态大小数组的顺序容器(Sequence Container)。跟任意其它类型容器一样,它能够存放各种类型的对象。可以简单的认为,向量是一个能够存放任意类型的动态数组。
容器特性:
1.顺序序列
顺序容器中的元素按照严格的线性顺序排序。可以通过元素在序列中的位置访问对应的元素。
2.动态数组
支持对序列中的任意元素进行快速直接访问,甚至可以通过指针算述进行该操作。提供了在序列末尾相对快速地添加/删除元素的操作。
3.能够感知内存分配器的
容器使用一个内存分配器对象来动态地处理它的存储需求。
实现代码:
void TestVector()
{
vector<studentInfo> students;
students.push_back(studentInfo("10021","Zhang san"));
students.push_back(studentInfo("10002","Li si"));
students.push_back(studentInfo("10003","Wang wu"));
students.push_back(studentInfo("10011","Wang Liu"));
students.push_back(studentInfo("10010","Wu Liu"));
students.push_back(studentInfo("10003","Wang wu"));
students.push_back(studentInfo("10002","Li si"));
outputCont("old student",cout,students.begin(),students.end());
vector<studentInfo>::iterator it = students.begin();
advance(it,2); //跳过两个元素
sort(it,students.end()); //按照升序排序
outputCont("sort student",cout,students.begin(),students.end());
for(vector<studentInfo>::iterator it = students.begin();it!=students.end();it++)
{
it->_strName = "xxx";
}
outputCont("new student",cout,students.begin(),students.end());
vector<studentInfo>::iterator te; //声明一个迭代器
te=students.begin();
for(;te!=students.end();te++) //迭代器访问vector容器(查)
{
cout<<*te<<"\t";
}
cout<<endl;
//向量中迭代器指向元素前增加一个元素x
te = students.begin();
te = students.insert(te,studentInfo("10022","Xiao ming"));
te = students.insert(te,studentInfo("10005","Xiao li"));
outputCont("insert after",cout,students.begin(),students.end());
//删除vector中某个元素
for(vector<studentInfo>::iterator it = students.begin();it!=students.end();)
{
if(it->_strNo=="10010")
it=students.erase(it); //当删除时erase函数自动指向下一个位置,就不需要进行++
else
it++; //当没有进行删除的时候,迭代器++,可以删除连续元素
}
outputCont("erase after",cout,students.begin(),students.end());
//students.clear(); //清空容器
}
运行结果:
可见 vector存储是允许里面拥有重复元素的。
3.输入一个字符串,用map统计每个字符出现的次数并输出字符及对应的次数
map(映射)是一种把键对象和值对象进行映射的集合。它的每一个元素都包含一对键对象和值对象,而值对象仍可以是Map类型,依次类推,这样就形成了多级映射。向map集合中加入元素时,必须提供一对键对象和值对象,从Map集合中检索元素时,只要给出键对象,就会返回对应的值对象。map内部是自动排序的。map可以使用it->first来访问键,使用it->second访问值。
实现代码:
void TestMap()
{
map<string,int> stu;
stu["01"] = 100;
stu["10"] = 99;
stu["05"] = 98;
stu["10"] = 95;
cout<<"old map:";
for(map<string,int>::iterator it=stu.begin();it!=stu.end();it++)
{
cout<<it->first<<":"<<it->second<<"\t";
}
cout<<endl;
//增加元素
//用insert函数插入pair
stu.insert(pair<string,int>("03", 98));
// 用insert函数插入value_type数据
stu.insert(map<string,int>::value_type("30",96));
// 用数组方式插入
stu["07"] = 56;
stu["12"] = 66;
stu["09"] = 60;
stu["33"] = 99;
stu["17"] = 100;
cout<<"insert after:";
for(map<string,int>::iterator it=stu.begin();it!=stu.end();it++)
{
cout<<it->first<<":"<<it->second<<"\t";
}
cout<<endl;
//删除元素
//迭代器刪除
map<string,int>::iterator it;
it = stu.find("05");
stu.erase(it);
cout<<"erase after:";
for(map<string,int>::iterator it=stu.begin();it!=stu.end();it++)
{
cout<<it->first<<":"<<it->second<<"\t";
}
cout<<endl;
int len=stu.size(); //获取到map中映射的次数
cout<<"len:"<<len<<endl;
//用迭代器范围刪除 : 把整个map清空
//stu.erase(stu.begin(), stu.end());
//等同于mapStudent.clear()
map<char,int> s;
char c;
do{
cin>>c; //输入下一个字符
if(isalpha(c)) //判断是否是字母
{
c=tolower(c); //将字母转换为小写
s[c]++; //将该字母的出现频率加1
}
}while(c!='.');
for(map<char,int>::iterator iter=s.begin();iter!=s.end();iter++)
{
cout<<iter->first<<":"<<iter->second<<"\t";
}
cout<<endl;
}
运行结果:
|