程序设计与算法(三)C++面向对象程序设计 (北大MOOC)

摘要:
头文件是<使用namespacestd;ClassMyQueue{intk;int;//多集合容器对象元素是有序的,可以重复公共;k(k){}//容器插入对象friendstream&a)//对象输入重载>运算符{intnum;num;}//输出对象friendstream&从容器中取出;a) //对象输出过载<

  C++中有两方面体现重用:1、面向对象的思想:继承和多态,标准类库  2、泛型程序设计的思想:模板机制,以及标准模板库STL

  标准模板库(Standard Template Library)就是一些常用数据结构和算法模板的集合,有了STL,不必再写太多的标准数据结构和算法,并且可以获得非常高的性能  

  STL六大部件:容器(Containers)、分配器(Allocators)、算法(Alogrithms)、迭代器(Iterators)、仿函数(Functors,头文件为<functional>)、适配器(转换器)(Adapters)

  程序设计与算法(三)C++面向对象程序设计 (北大MOOC)第1张

  一、容器(Containers)

  容器的定义:

  在数据存储上,有一种对象类型,它可以持有其它对象或指向其它对象的指针,这种对象类型就叫做容器。很简单,容器就是保存其它对象的对象,当然这是一个朴素的理解,这种“对象”还包含了一系列处理“其它对象”的方法。容器即物之所在,容器是STL的核心部件之一,是迭代器的依附,是算法作用的目标 

  容器的种类:

  顺序容器:是一种各元素之间有顺序关系的线性表,是一种线性结构的可序群集。顺序性容器中的每个元素均有固定的位置,除非用删除或插入的操作改变这个位置。顺序容器的元素排列次序与元素值无关,而是由元素添加到容器里的次序决定。顺序容器包括:vector(向量)、list(列表)、deque(队列)
  关联容器:关联式容器是非线性的树结构,更准确的说是二叉树结构。各元素之间没有严格的物理上的顺序关系,也就是说元素在容器中并没有保存元素置入容器时的逻辑顺序。但是关联式容器提供了另一种根据元素特点排序的功能,这样迭代器就能根据元素的特点“顺序地”获取元素。元素是有序的集合,默认在插入的时候按升序排列。关联容器包括:map(集合)、set(映射)、multimap(多重集合)、multiset(多重映射)
  容器适配器:本质上,适配器是使一种不同的行为类似于另一事物的行为的一种机制。容器适配器让一种已存在的容器类型采用另一种不同的抽象类型的工作方式实现。适配器是容器的接口,它本身不能直接保存元素,它保存元素的机制是调用另一种顺序容器去实现,即可以把适配器看作“它保存一个容器,这个容器再保存所有元素”。STL 中包含三种适配器:栈stack 、队列queue 和优先级队列priority_queue

  容器类自动申请和释放内存,因此无需new和delete操作。

  不同容器的使用方法:

  1、c++语言中,multiset 是 <set> 库中一个非常有用的类型,它可以看成一个序列,插入一个数,删除一个数都能够在O(logn)的时间内完成,而且他能时刻保证序列中的数是有序的,而且序列中可以存在重复的数

程序设计与算法(三)C++面向对象程序设计 (北大MOOC)第2张程序设计与算法(三)C++面向对象程序设计 (北大MOOC)第3张
/*
    输入n个整数,输出整数数列中大小排名前k的偶数
    测试用例:
    2
    9 4
    1 2 4 3 6 6 7 8 9
    3 2
    18 16 14
 */

#include <iostream>
#include <set>

using namespace std;

class MyQueue
{
    int k;  //创建对象时,k表示前k个偶数整数
    multiset < int, greater<int> > que; //multiset容器对象 元素有序且可以重复
public:

    MyQueue(int k):k(k) {}

    //容器插入对象
    friend istream & operator>>(istream&is, MyQueue &a) //对象输入 重载 >> 运算符
    {
        int num;
        is >> num;
        if (num % 2 == 0)
        {
            a.que.insert(num); //是偶数插入
        }
        return is;
    }

    //从容器输出对象
    friend ostream & operator <<(ostream&os, MyQueue &a) //对象输出 重载 << 运算符
    {
        multiset<int>::iterator p = a.que.begin(); //迭代器
        int count = 0;
        for (; count < a.k; p++)
        {
            if (count){
                os << " ";
            }            
            os << *p ; //输出元素
            count++;   //记录输出元素个数
        }
        return os;
    }
};

int main()
{
    int t;
    cin >> t;
    while(t--)
    {
        int n, k;
        cin >> n >> k;
        MyQueue q(k);
        for (int i = 0; i < n; ++i)
            cin >> q; //利用>>运算符重载 输入整数(插入到对象 q 的 multiset 容器中)
        cout<<q;
        cout << endl;
    }

    return 0;
}
View Code

  2、<vector> 容器的 for_each(iterator,iterator,pointer)(第三个参数:pointer是指向函数的指针:全局函数 或  函数对象-->临时对象)

程序设计与算法(三)C++面向对象程序设计 (北大MOOC)第4张

  临时对象,就是一种无名对象(unamed objects),临时对象类名之后直接加一对小括号 () 或者大括号 {}(列表初始化),并可指定初值,其意义相当于调用相应的构造函数并且不指定对象名

  函数对象(function object),形式上是一个类实例化的对象,本质上是为了实现某种与函数等价的功能,函数对象的思想是:用类来封装一个函数功能,然后用这个类实例化不同的函数对象,若一个类重载了运算符(),则该类的对象就成为函数对象

程序设计与算法(三)C++面向对象程序设计 (北大MOOC)第5张程序设计与算法(三)C++面向对象程序设计 (北大MOOC)第6张
/*
    完成以下程序,使得输入的整数x,以及若干正整数,将
大于x的正整数输出;然后输入若干字符串,将字符串长度大于x的字符串输出
    测试用例:
    2
    5 6
    1 3 59 30 2 40
    this is hello please me ha
    1 1
    4
    this
    输出:
    59,30,40,
    please,
    4,
    this,
 */

#include <algorithm> //for_each 头文件
#include <iostream>
#include <vector>

using namespace std;


class Printer
{
    int size;

public:
    Printer(int x) : size(x) {}

    void operator()(int x)  //运算符()重载
    {
        if (x > size)
            cout << x << ',';
    }

    void operator()(string str) //运算符()重载
    {
        if (str.size() > size)
            cout << str << ',';
    }
};

int main()
{
    int t;
    cin >> t;
    while(t--)
    {
        int n,x;
        cin >> x >> n;

        vector<int> intVec;
        for(int i = 0; i < n; ++i)
        {
            int y;
            cin >> y;
            intVec.push_back(y);
        }
        for_each(intVec.begin(), intVec.end(), Printer(x)); //Printer(x)是函数对象
        cout << endl;

        vector<string> strVec;
        for(int i = 0; i < n; ++i)
        {
            string str;
            cin >> str;
            strVec.push_back(str);
        }
        for_each(strVec.begin(), strVec.end(), Printer(x));
        cout << endl;
    }
    return 0;
}
View Code

  全局函数

程序设计与算法(三)C++面向对象程序设计 (北大MOOC)第7张程序设计与算法(三)C++面向对象程序设计 (北大MOOC)第8张
#include <iostream>
#include <vector>
#include <algorithm>  //for_each 

using namespace std;

//全局函数
void printElem(int elem, const char* prefix)
{
    cout << prefix << elem << endl;
}

int main()
{
    int ia[] = {1, 2, 3};
    vector<int> ivec(ia, ia + sizeof(ia) / sizeof(int));
    for_each(ivec.begin(), ivec.end(), bind2nd(ptr_fun(printElem), "Element:"));
    
    return 0;
}
View Code

  3、<list> 容器的 sort 参数:< 运算符重载,函数对象(重载 () 运算符),全局函数,<list>容器的 for_each 的参数为全局函数

程序设计与算法(三)C++面向对象程序设计 (北大MOOC)第9张程序设计与算法(三)C++面向对象程序设计 (北大MOOC)第10张
/*
三生三世

测试用例:3代表3个电视剧,以下是 每个电视剧的剧名 及 演员阵容、剧情和演技的分数
3
In the Name of People
98 97 99
Life After Life, Blooms Over Blooms
99 82 73
Ming Dynasty: 1566
97 100 100
输出:按分数(分别为演员阵容、剧情和演技的分数)从大到小排序3次,并按排序输出剧名

*/
#include <iostream>   //string
#include <list>       //list
#include <algorithm>  // sort
using namespace std;

class TV_Drama {
public:
    char name[100]; //电视剧
    int actor;  //演员阵容评分
    int story;  //剧情评分
    int acting_skill; //演技评分
    // 在此处补充你的代码
    TV_Drama(string _name, int _actor, int _story, int _acting_skill) :
            actor(_actor), story(_story), acting_skill(_acting_skill) {
        _name.copy(name, _name.size(), 0); //string类的函数
        name[_name.size()] = 0; //字符串结束符     name 电视剧剧名
    }
    bool operator <(const TV_Drama &obj) { //对象比较,重载比较运算符  <
        return actor > obj.actor;   //从高到低排序
    }
};


void Printer(const TV_Drama &obj) { //全局函数
    cout << obj.name << ';';
    //cout <<"--" << obj.actor << "--" << obj.story << "--" << obj.acting_skill<< endl;
}
bool comparator_1(const TV_Drama &o1, const TV_Drama &o2) { //全局函数
    return o1.story > o2.story;  //从高到低排序
}

class comparator_2 { //函数对象 ,重载了小括号 () 运算符
public:
    bool operator()(const TV_Drama &o1, const TV_Drama &o2) {
        return o1.acting_skill > o2.acting_skill;   //从高到低排序
    }
};

int main() {
    list<TV_Drama> lst;  //对象容器
    int n;
    cin >> n;
    char _name[100];
    int _actor, _story, _acting_skill;
    for (int i = 0; i < n; i++) {
        cin.ignore();  //cin.ignore()函数用于忽略或清除输入缓冲区中的一个或多个字符
        cin.getline(_name, 100);
        cin >> _actor >> _story >> _acting_skill;
        lst.push_back(TV_Drama(_name, _actor, _story, _acting_skill));
    }

    lst.sort(); //无参 默认对象从小到大,重载 < 运算符改为 从大到小
    for_each(lst.begin(), lst.end(), Printer);
    cout << endl;

    lst.sort(comparator_1);   //全局函数
    for_each(lst.begin(), lst.end(), Printer);
    cout << endl;

    lst.sort(comparator_2()); //函数对象
    for_each(lst.begin(), lst.end(), Printer);
    cout << endl;

    return 0;
}
View Code

  4、<map> 容器,单词统计

程序设计与算法(三)C++面向对象程序设计 (北大MOOC)第11张程序设计与算法(三)C++面向对象程序设计 (北大MOOC)第12张
#include <iostream>
#include <map>
#include <string>
#include <algorithm>
using namespace std;

/*单词计数器 */

string& strip(string &str)
{
    for (auto &ch : str)
        ch = tolower(ch);// 转成小写
    str.erase( remove_if ( str.begin(), str.end(), static_cast<int(*)(int)>(&ispunct) ), str.end());

    return str;
};

std::map<std::string, std::size_t> count()
{
    std::map<std::string, std::size_t> counts;
    for (string w; cin >> w; ++counts[strip(w)])
        ;
    return counts;
}

void println(std::map<std::string, std::size_t> const &m)
{
    for (auto const &kv : m)
    {
        cout << kv.first << " -- " << kv.second << endl;
    }
}

int main()
{
    println(count()); //count()函数返回的是map容器
    cin.clear();
    return 0;
}
View Code

免责声明:文章转载自《程序设计与算法(三)C++面向对象程序设计 (北大MOOC)》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Go go.mod入门动态任务定义和任务链下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

阻止Bootstrap 模态框点击背景空白处自动关闭

问题描述 模态框点击空白处,会自动关闭,怎么阻止关闭事件呢? 解决方法 在HTML页面中编写模态框时,在div初始化时添加属性 aria-hidden=”true” data-backdrop=”static”,即可。 <!-- 模态框(Modal) --> <div class="modal fade" id="myModal" t...

11.ThinkPHP分页

分页实现 ThinkPHP5.1内置了分页实现,要给数据添加分页输出功能变得非常简单,可以直接在Db类查询的时候调用paginate方法: 官方Demo // 查询状态为1的用户数据 并且每页显示10条数据 $list = Db::name('user')->where('status',1)->paginate(10); // 把分页数据赋值...

xml之XSLT

 1、XSLT是什么  XSLT是XSL的子集,XSL是样式表。XSLT的作用:将XML文档转化成HTML,做的是中间转换者。  而主要需要学习的是XSLT(XSLTransformation)。  2、转换过程   3、XSL样式表的表的结构 引用XSL样式的XML文件的引用方式:   4、XSLT详细结构 1》有独立的命名空间 2》要执行XSL...

lua二进制操作函数

  由于 Lua 脚本语言本身不支持对数字的二进制操作(例如 与,或,非 等操作),MUSHclient 为此提供了一套专门用于二进制操作的函数,它们都定义在一个“bit”表中,使用时只要requre “bit”即可。 bit.ashr - 带符号的按位右移   此函数需要两个整数作为参数。第一个参数可以带有符号,是被以为的数,第二个参数是一个无符号整数,...

AndroidManifest.xml文件详解(meta-data)

http://blog.csdn.net/think_soft/article/details/7567189 语法(SYNTAX): <meta-dataandroid:name="string"           android:resource="resource specification"           android:value...

Vue跨层级传递slot的方法

因为业务需要,我们的vue组件分了很多层。但我需要在父组件通过slot指定模板,但不在子组件渲染,而是在孙组件或是再下方的组件去渲染。 比如,我有一个通用的A组件,A组件内引用了B组件,B组件又引用了C组件。C组件的模板内有一部分是需要在A组件中来配置的。 因为中间间隔了1层以上的组件,所以没法通过一般的slot方式解决。于是研究了一下vue的scoped...