C++提高编程(三)

1 STL常用容器
1.1 vector容器
1.1.1 vector基本概念
  • 功能:vector数据结构和数组非常相似,也称为单端数组

  • vector与普通数组区别:不同之处在于数组是静态空间,而vector可以动态扩展

  • 动态扩展:并不是在原空间之后续接新空间,而是找更大的内存空间,然后将原数据拷贝新空间,释放原空间。

  • vector容器的迭代器是支持随机访问的迭代器

例图:

在这里插入图片描述

1.1.2 vector构造函数

功能描述:创建vector容器

函数原型:

  • vectorv; //采用模板实现类实现,默认构造函数

  • vector(v.begin(),v.end()); //将v[begin(),end())区间中的元素拷贝给本身

  • vector(n,elem); //构造函数将n个elem拷贝给本身

  • vector(const vector &vec); //拷贝构造函数

    #include <iostream>
    #include<vector>
    using namespace std;
    
    void printVector(vector<int>&v) {
        for (vector<int>::iterator it = v.begin(); it != v.end(); it++) {
            cout << *it << " ";
        }
        cout << endl;
    }
    //vector容器构造
    void test01() {
        vector<int>v1;//无参构造,默认构造
        for (int i = 0; i < 10; i++) {
            v1.push_back(i);
        }
        printVector(v1);
    
        //通过区间方式进行构造
        vector<int>v2(v1.begin(), v1.end());
        printVector(v2);
    
        //n个elem方式构造
        vector<int>v3(10, 100);
        printVector(v3);
    
        //拷贝构造
        vector<int>v4(v3);
        printVector(v4);
    }
    int main() {
        test01();
        system("pause");
        return 0;
    }
    

    输出结果为:

    在这里插入图片描述

1.1.3 vector赋值操作

功能描述:给vector容器进行赋值

函数原型

  • vector&operator=(const vector &vec); //重载等号操作符
  • assign(beg,end); //将[beg,end)区间中的数据拷贝赋值给本身
  • assign(n,elem); //将n个elem拷贝赋值给本身
#include <iostream>
#include<vector>
using namespace std;

void printVector(vector<int>&v) {
    for (vector<int>::iterator it = v.begin(); it != v.end(); it++) {
        cout << *it << " ";
    }
    cout << endl;
}
//vector赋值
void test01() {
    vector<int>v1;
    for (int i = 0; i < 10; i++) {
        v1.push_back(i);
    }
    printVector(v1);

    //赋值  operator=
    vector<int>v2;
    v2 = v1;
    printVector(v2);

    //assign
    vector<int>v3;
    v3.assign(v1.begin(), v1.end());
    printVector(v3);

    //n个elem方式赋值
    vector<int>v4;
    v4.assign(10, 100);
    printVector(v4);
}
int main() {
    test01();
    system("pause");
    return 0;
}

输出结果为:

在这里插入图片描述

1.1.4 vector容量和大小

功能描述:对vector容器的容量和大小操作

函数原型:

在这里插入图片描述

#include <iostream>
#include<vector>
using namespace std;

void printVector(vector<int>&v) {
    for (vector<int>::iterator it = v.begin(); it != v.end(); it++) {
        cout << *it << " ";
    }
    cout << endl;
}

//vector容器的容量和大小操作

void test01() {
    vector<int>v1;
    for (int i = 0; i < 10; i++) {
        v1.push_back(i);
    }
    printVector(v1);

    if (v1.empty())//为真,代表容器为空
    {
        cout << "v1为空" << endl;
    }
    else {
        cout << "v1不为空" << endl;
        cout << "v1的容量为:" << v1.capacity() << endl;
        cout << "v1的大小为:" << v1.size() << endl;//容量永远>=大小
    }

    //重新指定大小
    //利用重载版本,可以指定默认填充值,参数2
    v1.resize(15,88);//重新指定大小为15,多出来的用88填充,没写用0填充
    printVector(v1);//如果重新指定的比原来长了,默认用0填充新的位置

    v1.resize(5);
    printVector(v1);//如果重新指定的比原来短了,超出部分会被删除
}
int main() {
    test01();
    system("pause");
    return 0;
}

输出结果为:

在这里插入图片描述

1.1.5 vector插入和删除

功能描述:对vector容器进行插入、删除操作

函数原型:

在这里插入图片描述

#include <iostream>
#include<vector>
using namespace std;

//vector插入和删除

void printVector(vector<int>&v) {
    for (vector<int>::iterator it = v.begin(); it != v.end(); it++) {
        cout << *it << " ";
    }
    cout << endl;

}
void test01() {
    vector<int>v1;
    //尾插
    v1.push_back(10);
    v1.push_back(70);
    v1.push_back(50);
    v1.push_back(90);

    //遍历
    printVector(v1);

    //尾删
    v1.pop_back();//删除末尾最后一个数字
    printVector(v1);

    //插入   第一个参数是迭代器
    v1.insert(v1.begin(), 100);//在最前面插入一个数字
    printVector(v1);

    v1.insert(v1.begin(), 3, 88);//在最前面插入n个数字
    printVector(v1);

    //删除  第一个参数也是迭代器
    v1.erase(v1.begin());//删除最前面的一个数字
        printVector(v1);

    //清空
    // v1.erase(v1.begin(), v1.end());//把最前面和最后面中间的全部数字删掉,空容器
    v1.clear();
        printVector(v1);
}
int main() {
    test01();
    system("pause");
    return 0;
}

输出结果为:

在这里插入图片描述

1.1.6 vector数据存取

功能描述:对vector数据的存取操作

函数原型:

  • at(int idx); //返回索引idx所指的数据
  • operator[]; //返回索引idx所指的数据
  • front(); //返回容器中第一个数据元素
  • back(); //返回容器中最后一个数据元素
#include <iostream>
#include<vector>
using namespace std;

//vector容器数据存取操作
void test01() {
    vector<int>v1;
    for (int i = 0; i < 10; i++) {
        v1.push_back(i);
    }

    for (int i = 0; i < v1.size(); i++) {
        cout << v1[i] << " ";//利用[]的方式来访问数组中的元素
    }
    cout << endl;

//利用at方式访问元素
    for (int i = 0; i < v1.size(); i++) {
        cout << v1.at(i) << " ";
    }
    cout << endl;
   
//返回第一个元素
    cout << "第一个元素为:" << v1.front() << endl;

//获取最后一个元素
    cout << "最后一个元素为" << v1.back() << endl;
}
int main() {
    test01();
    system("pause");
    return 0;
}

输出结果为:

在这里插入图片描述

1.1.7 vector互换容器

功能描述:实现两个容器内元素进行互换

函数原型:swap(vec); //将vec与本身的元素互换

例图:

在这里插入图片描述

#include <iostream>
#include<vector>
using namespace std;

//vector容器互换
void printVector(vector<int>&v) {
    for (vector<int>::iterator it = v.begin(); it != v.end(); it++) {
        cout << *it << " ";
    }
    cout << endl;
}


//1、基本使用
void test01() {
    vector<int>v1;
    for (int i = 0; i < 10; i++) {
        v1.push_back(i);
    }

    //互换前的打印
    cout << "交换前:" << endl;
    printVector(v1);

    vector<int>v2;
    for (int i = 10; i > 0; i--) {
        v2.push_back(i);

    }
    printVector(v2);

    cout << "交换后:" << endl;
    v1.swap(v2);
    printVector(v1);
    printVector(v2);
}


//2、实际用途
//巧用swap可以收缩内存空间
void test02() {
    vector<int>v;
    for (int i = 0; i < 10000000; i++) {
        v.push_back(i);
    }
    cout << "v的容量为:" << v.capacity() << endl;
    cout << "v的大小为:" << v.size() << endl;

    v.resize(3);//重新指定大小
    cout << "v的容量为:" << v.capacity() << endl;
    cout << "v的大小为:" << v.size() << endl;

    //巧用swap收缩内存
    vector<int>(v).swap(v);
    cout << "v的容量为:" << v.capacity() << endl;
    cout << "v的大小为:" << v.size() << endl;

}
int main() {
    test01();
    test02();
    system("pause");
    return 0;
}

输出结果为:

在这里插入图片描述

1.1.8 vector预留空间

功能描述:减少vector在动态扩展容量时的扩展次数

函数原型:reserve(int len); //容器预留len个元素长度,预留位置不初始化,元素不可访问

#include <iostream>
#include<vector>
using namespace std;

//vector容器  预留空间
void test01() {
    vector<int>v;

    //利用reserve预留空间
    v.reserve(100000);
    int num = 0;//统计开辟次数
    int* p = NULL;
    for (int i = 0; i < 100000; i++) {
        v.push_back(i);
        if (p != &v[0]) {
            p = &v[0];
            num++;
        }
    }
    cout << "num=" << num << endl;
}
int main() {
    test01();
    system("pause");
    return 0;
}

输出结果为:

在这里插入图片描述

1.2 deque容器
1.2.1 deque容器基本概念

功能:对端数组,可以对头端、尾端进行插入删除操作

deque与vector区别:

  • vector对于头部的插入删除效率低,需要移动元素,数据量大,效率越低
  • deque相对而言,对头部的插入和删除速度会比vector快
  • vector访问元素时的速度会比deque快,这和两者内部实现有关

例图:

在这里插入图片描述

deque内部工作原理:

deque内部有一个中控器,维护每段缓冲区中的内容,缓冲区中存放真实数据

中控器维护的是每个缓冲区的地址,使得使用deque时像一片连续的内存空间

例图:

在这里插入图片描述

  • deque容器也是支持随机访问的
1.2.2 deque构造函数

功能描述:deque容器构造

函数原型:

  • dequedeqT; //默认构造形式
  • deque(beg,end); //构造函数将[beg,end)区间中的元素拷贝给本身
  • deque(n,elem); //构造函数将n个elem拷贝给本身
  • deque(const deque &deq); //拷贝构造函数
#include <iostream>
#include<deque>
using namespace std;

void printDeque(const deque<int>&d) {//只读状态
    for (deque<int>::const_iterator it = d.begin(); it != d.end(); it++) {
        //*it=100;//容器中的数据加了const现在不可以修改了
        cout << *it << " ";
    }
    cout << endl;
}
//deque容器--构造函数
void test01() {
    deque<int>d1;
    for (int i = 0; i < 10; i++) {
        d1.push_back(i);
    }
    printDeque(d1);

    deque<int>d2(d1.begin(), d1.end());
    printDeque(d2);

    deque<int>d3(8, 88);
    printDeque(d3);

    deque<int>d4(d3);
    printDeque(d4);

}
int main() {
    test01();
    system("pause");
    return 0;
}

输出结果为:

在这里插入图片描述

1.2.3 deque赋值操作

功能描述:给deque容器进行赋值

函数原型:

  • deque& operator=(const deque &deq); //重载等号操作符
  • assign(beg,end); //将[beg,end)区间中的数据拷贝赋值给本身
  • assign(n,elem); //将n个elem拷贝赋值给本身;
#include <iostream>
#include<deque>
using namespace std;

void  printDeque(const deque<int>& d) {
    for (deque<int>::const_iterator it=d.begin();it!=d.end();it++) {
        cout << *it << " ";
    }
    cout << endl;
}
//deque容器--赋值操作
void test01() {
    deque<int>d1;
    for (int i = 0; i < 10; i++) {
        d1.push_back(i);
    }
    printDeque(d1);

    //operator=赋值
    deque<int>d2;
    d2 = d1;
    printDeque(d2);

    //assign赋值
    deque<int>d3;
    d3.assign(d1.begin(), d1.end());
    printDeque(d3);

    deque<int>d4;
    d4.assign(3, 88);
    printDeque(d4);

}
int main() {
    test01();
    system("pause");
    return 0;
}

输出结果为:

在这里插入图片描述

1.2.4 deque大小操作

功能描述:对deque容器的大小进行操作

函数原型:

  • deque.empty(); //判断容器是否为空
  • deque.size(); //返回容器中元素的个数
  • deque.resize(num); //重新指定容器的长度为num,若容器变长,则以默认值填充新位置

​ //如果容器变短,则末尾超出容器长度的元素会被删除。

  • deque.resize(num,elem); //重新指定容器的长度为num,若容器变长,则以elem值填充新位置,

​ //如果容器变短,则末尾超出容器长度的元素会被删除。

#include <iostream>
#include<deque>;
using namespace std;

void  printDeque(const deque<int>& d) {
    for (deque<int>::const_iterator it=d.begin();it!=d.end();it++) {
        cout << *it << " ";
    }
    cout << endl;
}
//deque容器--大小操作
void test01() {
    deque<int>d1;
    for (int i = 0; i < 10; i++) {
        d1.push_back(i);
    }
    printDeque(d1);

    if (d1.empty()) {
        cout << "d1为空" << endl;
    }
    else {
        cout << "d1不为空" << endl;
        cout << "d1的大小为:" << d1.size() << endl;
        //deque容器没有容量概念,有缓冲区可以无限放
    }
    //重新指定大小
   // d1.resize(15);
   // printDeque(d1);

    d1.resize(15,88);
    printDeque(d1);

    d1.resize(5);
    printDeque(d1);
}
int main() {
    test01();
    system("pause");
    return 0;
}

输出结果为:

在这里插入图片描述

1.2.5 deque插入和删除

功能描述:向deque容器中插入和删除数据

函数原型:

在这里插入图片描述

#include <iostream>
#include<deque>
using namespace std;

//deque容器--插入和删除

void  printDeque(const deque<int>& d) {
    for (deque<int>::const_iterator it=d.begin();it!=d.end();it++) {
        cout << *it << " ";
    }
    cout << endl;
}
//两端操作
void test01() {
    deque<int>d1;

    //尾插
    d1.push_back(99);
    d1.push_back(88);

    //头插
    d1.push_front(66);
    d1.push_front(44);

    //44  66  99  88
    printDeque(d1);
    //尾删
    d1.pop_back();
    printDeque(d1);

    //头删
    d1.pop_front();
    printDeque(d1);


}
void test02() {
    deque<int>d1;
    d1.push_back(10);
    d1.push_back(20);
    d1.push_front(66);
    d1.push_front(88);

    printDeque(d1);

    //insert插入
    d1.insert(d1.begin(), 99);
    printDeque(d1);

    d1.insert(d1.begin(), 5,99);
    printDeque(d1);

    //按照区间进行插入
    deque<int>d2;
    d2.push_back(6);
    d2.push_back(8);
    d2.push_back(10);

    d1.insert(d1.begin(), d2.begin(),d2.end());
    printDeque(d1);
}

void test03() {
    deque<int>d1;
    d1.push_back(10);
    d1.push_back(20);
    d1.push_front(66);
    d1.push_front(88);

    printDeque(d1);
    //删除
    deque<int>::iterator it = d1.begin();
    it++;//迭代器发生偏移,删除第二个元素
    d1.erase(it);
    printDeque(d1);

    //按照区间方式删除
    d1.erase(d1.begin(), d1.end());
    //清空
    // d1.clear();
    printDeque(d1);
}
int main() {
    test01();
    test02();
    test03();
    system("pause");
    return 0;
}

输出结果为:

在这里插入图片描述

1.2.6 deque数据存取

功能描述:对deque中的数据进行存取操作

函数原型:

  • at(int idx); //返回索引idx所指的数据
  • operator[]; //返回索引idx所指的数据
  • front(); //返回容器中第一个数据元素
  • back(); //返回容器中最后一个数据元素
#include <iostream>
#include<deque>
using namespace std;

//deque容器数据存取
void test01() {
    deque<int>d;
    d.push_back(88);
    d.push_back(66);
    d.push_back(55);
    d.push_front(100);
    d.push_front(40);
    d.push_front(90);

    //通过[]方式访问元素
    //90 40 100 88 66 55
    for (int i = 0; i < d.size(); i++){
        cout << d[i] << " ";

    }
    cout << endl;

    //通过at方式访问元素
    for (int i = 0; i < d.size(); i++) {
        cout << d.at(i) <<" ";
    }
    cout << endl;
    cout << "第一个元素为:" << d.front() << endl;
    cout << "最后一个元素为:" << d.back() << endl;
}
int main() {
    test01();
    system("pause");
    return 0;
}

输出结果为:

在这里插入图片描述

1.2.7 deque排序

功能:利用算法实现对deque容器进行排序

算法:sort(iterator beg,iterator end) //对beg和end区间元素进行排序

#include <iostream>
#include<deque>
#include<algorithm>//标准算法头文件
using namespace std;

//通过迭代器做一个打印输出
void  printDeque(const deque<int>& d) {
    for (deque<int>::const_iterator it=d.begin();it!=d.end();it++) {
        cout << *it << " ";
    }
    cout << endl;
}

//deque容器排序
void test01() {
    deque<int>d;
    d.push_back(66);
    d.push_back(88);
    d.push_back(99);
    d.push_front(55);
    d.push_front(58);
    d.push_front(98);

    printDeque(d);
    //排序:默认排序规则是从小到大,升序
    //对于支持随机访问的迭代器的容器,都可以利用sort算法直接对其进行排序
    //vector容器也可以利用sort进行排序
    sort(d.begin(), d.end());
    cout << "排序后:" << endl;
    printDeque(d);
}
int main() {
    test01();
    system("pause");
    return 0;
}

输出结果为:

在这里插入图片描述

1.3 案例–评委打分

案例描述:

有5名选手:选手ABCDE,10个评委分别对每一名选手打分,去除最高分和最低分,取平均分

实现步骤:

  • 创建5名选手,放到vector中
  • 遍历vector容器,取出来每一个选手,执行for循环,可以10个评分打分存到deque容器中
  • sort算法对deque容器中分数排序,去除最高分和最低分
  • deque容器遍历一遍,累加总分
  • 获取平均分
#include <iostream>
#include<string>
#include<vector>
#include<deque>
#include<algorithm>
#include<ctime>
using namespace std;

/*有5名选手:选手ABCDE,10个评委分别对每一名选手打分,去除最高分和最低分,取平均分*/
//选手类
class Person {
public:
    Person(string name,int score) {
        this->m_Name = name;
        this->m_score = score;
    }
    string m_Name;//选手姓名
    int m_score;//平均分
};
void creatPerson(vector<Person>&v) {
    string nameSeed = "ABCDE";
    
    for (int i = 0; i < 5; i++) {
        string name = "选手";
        name += nameSeed[i];

        int score = 0;
        Person p(name, score);

        //将创建的Person对象放入到容器中
        v.push_back(p);
    }
}
void setScore(vector<Person>&v) {
    for (vector<Person>::iterator it = v.begin(); it != v.end(); it++) {
        //将评委的分数放入到deque容器中
        deque<int>d;
        for (int i = 0; i < 10; i++) {
            int score = rand() % 41 + 60; //60~100
            d.push_back(score);
        }
        cout << "姓名:" << it->m_Name << "打分:"  << endl;
        for (deque<int>::iterator dit = d.begin(); dit != d.end(); dit++) {
            cout << *dit << " ";
        }
        cout << endl;
        //排序
        sort(d.begin(), d.end());
        //去除最高分和最低分
        d.pop_front();
        d.pop_back();

        //取平均分
        int sum = 0;
        for (deque<int>::iterator dit = d.begin(); dit != d.end(); dit++) {
            sum += *dit;//累加每个评委的分数
        }
        int avg = sum / d.size();
        //将平均分赋值给选手
        it->m_score = avg;
    }
}
void showScore(vector<Person>&v) {
    for (vector<Person>::iterator it = v.begin(); it != v.end(); it++) {
        cout << "姓名:" << it->m_Name << "平均分:" << it->m_score << endl;
    }
}
int main() {
    //随机数种子
    srand((unsigned int)time(NULL));


    //1、创建5名选手
    vector<Person>v;//存放选手的容器
    creatPerson(v);
    //测试
    for (vector<Person>::iterator it = v.begin(); it != v.end();it++) {
        cout << "姓名:"<<(*it).m_Name << "分数:"<<(*it).m_score << endl;
   }
    //2、给5名选手打分
    setScore(v);

    //3、显示最后得分
    showScore(v);
    system("pause");
    return 0;
}

输出结果为:

在这里插入图片描述

更多推荐