c++实验四


1.SLT算法
STL算法本身是一种函数模版
通过迭代器获得输入数据
通过函数对象对数据进行处理
通过迭代器将结果输出
STL算法是通用的,独立于具体的数据类型、容器类型

2.SLT算法分为:
不可变序列算法
可变序列算法
排序和搜索算法
数值算法

3.迭代器:
迭代器是算法和容器的桥梁
迭代器用作访问容器中的元素
算法不直接操作容器中的数据,而是通过迭代器间接操作
算法和容器独立
增加新的算法,无需影响容器的实现
增加新的容器,原有的算法也能适用

一、撰写自己的算法和函数,结合容器和迭代器解决序列变换(如取反、平方、立方),像素变换(二值化、灰度拉伸)

代码如下:

void transInv(int a[],int b[],int nNum) //取反
{
    for(int i=0;i<nNum;i++)
    {
        b[i] = -a[i];
    }
}

void transSqr(int a[],int b[],int nNum)     //平方
{
    for(int i=0;i<nNum;i++)
    {
        b[i] = a[i]*a[i];
    }
}

void transCube(int a[],int b[],int nNum)     //立方
{
    for(int i=0;i<nNum;i++)
    {
        b[i] = a[i]*a[i]*a[i];
    }
}


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>
T InvT(T a)
{
    return -a;
}

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 strNme,ostream& os, T begin, T end)
{
    os<<strNme<<":";
    for(;begin!=end;begin++)
    {
        os<<*begin<<"\t";
    }
    os<<endl;
}

template<typename T>
class MyThreshold{          //图像二值化
public:
    MyThreshold(int n=128):_nThreshold(n){}
    int operator()(T val)
    {
        return val<_nThreshold?0:1;
    }
    int _nThreshold;
};

template<typename T>
bool mycomp(T a, T b)
{
    return a>b;
}
template <typename T>               //模板
class MyCompC                       //排序:降序
{
public:
    bool operator()(const T& x, const T& y) const           //双目运算符
    {
        return  x>y;
    }
};

void Test()
{
    const int N = 5;
    int a[N] = {1,2,4,3,5};
    outputCont("a",cout,a,a+N);             //a:1 2 4 3 5
    int b[N];
    vector<double> vb(N);
    vector<double> vc(N);
    transInv(a,b,N);
    outputCont("Inv a",cout,b,b+N);             //负数Inv a:-1 -2 -4 -3 -5
    transSqr(a,b,N);
    outputCont("Sqr a",cout,b,b+N);             //平方Sqr a:1 4 16 9 25
    transCube(a,b,N);
    outputCont("Cube a",cout,b,b+N);            //立方Cube a:1 8 64 27 125
    transInvT(a,b,N);
    outputCont("Inv a T",cout,b,b+N);           //负数Inv a T:-1 -2 -4 -3 -5

    //获得容器首,尾迭代器
    transInvT(a,a+N,b,InvT<int>);
    transInvT(a,a+N,vb.begin(),InvT<int>);
    outputCont("Inv a by iter",cout,vb.begin(),vb.end());           //Inv a by iter:-1 -2 -4 -3 -5

    //图像二值化
    transInvT(a,a+N,vb.begin(),MyThreshold<int>(2));
    outputCont("Inv a by treshold",cout,vb.begin(),vb.end());       //Inv a by treshold:0 1 1 1 1
    
     sort(a,a+N,mycomp<int>);
    sort(a,a+N,greater<int>());                   //greater内容
    sort(a,a+N,MyCompC<int>());
    outputCont("a sorted",cout,a,a+N);             //降序a sorted:5 4 3 2 1
    vb.swap(vc);                                //将vb和vc两容器内容交换
}

int main()
{
//    cout << "Hello World!" << endl;
    Test();
    return 0;
}

测试结果
在这里插入图片描述

二、用set存储学生信息,并进行增删改查操作

容器 分为三种:
顺序容器
array(数组)、vector(向量)、deque(双端队列)、forward_list(单链表)、list(列表)
(有序)关联容器
set(集合)、multiset(多重集合)、map(映射)、multimap(多重映射)
无序关联容器
unordered_set (无序集合)、unordered_multiset(无序多重集合)
unordered_map(无序映射)、unorder_multimap(无序多重映射)

1.顺序容器的接口(不包含单向链表(forward_list)和数组(array))
①构造函数
列表初始化,如vector arr = {1,4,5,7};
②赋值函数
assign
③插入函数
insert(iterator pos, const T& v), 在pos位置插入后,返回新插入元素的迭代器
push_front(只对list和deque), push_back,
emplace_front、emplace 和 emplace_back,这些操作构造而不是拷贝元素到容器中,这些操作分别对应push_front、insert 和push_back,允许我们将元素放在容器头部、一个指定的位置和容器尾部。
④删除函数
erase,clear,pop_front(只对list和deque) ,pop_back
⑤首尾元素的直接访问
front,back
⑥改变大小
resize

2.关联容器的特点和接口
①关联容器的特点
每个关联容器都有一个键(key)
可以根据键高效地查找元素
②接口
构造:列表初始化,如map<string, int> id_map = {{“小明”, 1}, {“李华”, 2}}
插入:insert
删除:erase
查找:find
定界:lower_bound、upper_bound、equal_range
计数:count

集合(set)
集合用来存储一组无重复的元素。由于集合的元素本身是有序的,可以高效地查找指定元素,也可以方便地得到指定大小范围的元素在容器中所处的区间。

代码如下(示例):

class studentInfo{                  //学生这个类
public:
    studentInfo(string strNo,string strName){
        _strNo = strNo;             //学号
        _strName = strName;         //姓名
    }
    string _strNo;
    string _strName;
    friend ostream& operator<<(ostream& os, const studentInfo& info)        //学号姓名的输出
    {
       os<<info._strNo<<" "<<info._strName;
        return os;
   }
   friend bool operator< (const studentInfo& info1, const studentInfo& info2){       //学号比较的函数
        return info1._strNo<info2._strNo;
    }
};

//集合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"));
    set<studentInfo> studentSet(students.begin(),students.end());
    outputCont("student_strName set",cout,studentSet.begin(),studentSet.end());

    studentSet.insert(studentInfo("10030", "HHL"));         //增加
    outputCont("student_strName add", cout, studentSet.begin(), studentSet.end());

    studentSet.erase(studentInfo("10003","Wang wu"));     //删除
    outputCont("student_strName del",cout,studentSet.begin(),studentSet.end());

    students[2]._strName = "hhl";          //第三个改成hhl
    set<studentInfo> studentmodify(students.begin(),students.end());
    outputCont("student_strName mod",cout,studentmodify.begin(),studentmodify.end());
	
	//查未实现


}

测试结果
在这里插入图片描述

三、输入一个字符串,用map统计每个字符出现的次数并输出字符及对应的次数

映射:
映射与集合同属于单重关联容器,它们的主要区别在于,集合的元素类型是键本身,而映射的元素类型是由键和附加数据所构成的二元组。
在集合中按照键查找一个元素时,一般只是用来确定这个元素是否存在,而在映射中按照键查找一个元素时,除了能确定它的存在性外,还可以得到相应的附加数据。

代码如下:

//映射
void TestMap()
{
    map<string,int> stu;
    stu["01"] = 100;
    stu["10"] = 99;         //重复元素
    stu["05"] = 98;
    stu["10"] = 95;         //重复元素
    for(map<string,int>::iterator it=stu.begin();it!=stu.end();it++)
    {
        cout<<it->first<<" "<<it->second<<endl;
    }


    map<char, int> s;	//用来存储字母出现次数的映射
    char c;		//存储输入字符
    cout<<"please input"<<endl;
    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 << "  ";
        cout << endl;


}
void Test()
{
    cout<<"TestMap:"<<endl;
    TestMap();                  //01 100;05 98;10 95;
}

int main()
{
//    cout << "Hello World!" << endl;
    Test();
    return 0;
}
    

测试结果
在这里插入图片描述

代码中重复的stu[“10”] = 99; stu[“10”] = 95;只有最后一个输出。set是根据元素值进行排序的集合,所插入的元素在集合中唯一,不存在重复元素

总结

set容器:set是STL中一种标准关联容器。它底层使用平衡的搜索树——红黑树实现,插入删除操作时仅仅需要指针操作节点即可完成,不涉及到内存移动和拷贝,所以效率比较高。
set作为一个容器也是用来存储同一数据类型的数据类型,并且能从一个数据集合中取出数据,在set中每个元素的值都唯一,而且系统能根据元素的值自动进行排序。应该注意的是set中数元素的值不能直接被改变。C++ STL中标准关联容器set, multiset, map, multimap内部采用的就是一种非常高效的平衡检索二叉树:红黑树,也成为RB树(Red-Black Tree)。RB树的统计性能要好于一般平衡二叉树,所以被STL选择作为了关联容器的内部结构。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值