黑马程序员C++提高编程笔记

黑马程序员C++提高编程笔记

[toc]

1. STL

1.1 STL

  • 标准模版库(Standard Templete Library)

1.2 STL基本概念:

  • STL六大组件:

    • 容器:各种数据结构、如vector、list、map、set、deque
    • 算法:各种常见的算法、比如sort、find、copy、for_each
    • 迭代器:扮演了容器和算法之间的粘合剂
    • 仿函数:行为类似函数、可以作为 算法的某种策略
    • 适配器:一种用来修饰容器或者仿函数或迭代器接口的东西
    • 空间配置器:负责空间的配置与管理
  • 容器就是用来存放数据的

  • STL容器就是将一些运用最广泛的数据结构实现出来

  • 常用的数据结构:数组、链表、二叉树、栈、队列、集合、映射表

  • 这些容器分为序列式容器和关联式容器

    • 序列式容器强调值的排序,里面每个值都有固定的位置
    • 关联式容器:二叉树结构、各元素之间没有严格的物理上的顺序关系

1.2 容器算法

  • 算法
    • 算法就是用有限的步骤,解决数学或者逻辑上的问题
    • 算法分为质变算法和非质变算法
      • 质变算法是指运算过程中会更改区间内的元素,例如拷贝、删除、替换
      • 非质变算法是指运算过程中不会更改区间内的元素。例如查找、计数、遍历、寻找极值等

1.3 迭代器

  • 迭代器就是容器和算法之间的粘合剂
    • 提供一种方法,使之能够依序访问容器内的各个元素,而不暴露容器的内部表示方式
//
//  main.cpp
//  迭代器初识
//
//  Created by OnlyBei on 2021/9/24.
//

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

void myPrint(int val) {
    cout << val << endl;
}

int main(int argc, const char * argv[]) {
    // insert code here...
    vector<int> v;
    v.push_back(10);
    v.push_back(20);
    v.push_back(30);
    v.push_back(40);
    
    vector<int>::iterator pBegin = v.begin();
    vector<int>::iterator pEnd = v.end();
    
    // 第一种遍历方式
    while(pBegin != pEnd) {
        cout << *pBegin << endl;
        pBegin++;
    }
    
    // 第二种
    for(vector<int>::iterator it = v.begin(); it != v.end(); it++) {
        cout << *it << endl;
    }
    
    for_each(v.begin(), v.end(), myPrint);
    
}

1.4 vector存放自定义数组

//
//  main.cpp
//  vector中存放自定义数据类型
//
//  Created by OnlyBei on 2021/9/24.
//

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

class Person {
public:
    Person(string name, int age) {
        this->m_Name = name;
        this->m_Age = age;
    }
public:
    string m_Name;
    int m_Age;
};

void test01() {
    vector<Person> v;
    
    Person p1("aaa", 10);
    Person p2("bbb", 20);
    Person p3("ccc", 30);
    Person p4("ddd", 40);
    
    v.push_back(p1);
    v.push_back(p2);
    v.push_back(p3);
    v.push_back(p4);
    
    for(vector<Person>::iterator it = v.begin(); it != v.end(); it++) {
//        cout << "姓名:" << it->m_Name << "年龄:" << it->m_Age << endl;
        cout << "姓名:" << (*it).m_Name << "年龄:" << (*it).m_Age << endl;

    }

}

void test02() {
    vector<Person*> v;
    
    Person p1("aaa", 10);
    Person p2("bbb", 20);
    Person p3("ccc", 30);
    Person p4("ddd", 40);
    
    v.push_back(&p1); // 取地址
    v.push_back(&p2);
    v.push_back(&p3);
    v.push_back(&p4);
    
    for(vector<Person*>::iterator it = v.begin(); it != v.end(); it++) {
      // 双重指针
//        cout << "2姓名:" << (*(*it)).m_Name << "年龄:" << (*(*it)).m_Age << endl;
        cout << "2姓名:" << (*it)->m_Name << "年龄:" << (*it)->m_Age << endl;

    }

}

int main(int argc, const char * argv[]) {
    // insert code here...
//    test01();
    test02();
}

1.5 vector的嵌套结构

//
//  main.cpp
//  vector中的嵌套数据类型
//
//  Created by OnlyBei on 2021/9/24.
//

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

void test() {
    vector<vector<int> > v;
    
    vector<int> v1;
    vector<int> v2;
    vector<int> v3;
    vector<int> v4;
    
    for(int i = 0; i < 4; i++) {
        v1.push_back(i);
        v2.push_back(i + 4);
        v3.push_back(i + 8);
        v4.push_back(i + 12);
    }
    
    v.push_back(v1);
    v.push_back(v2);
    v.push_back(v3);
    v.push_back(v4);
    
    for(vector<vector<int> >::iterator it = v.begin(); it != v.end(); it++) {
        for(vector<int>::iterator vit = (*it).begin(); vit != (*it).end(); vit++) {
            cout << *vit << " ";
        }
        cout << endl;
    }

}

int main(int argc, const char * argv[]) {
    // insert code here...
    test();
}

2. String容器

2.0 前置知识:

  • 在C语言中:

    • char是定义一个字符,存储一个字符,占一个字节。
    • string是定义一个字符串,存储的是一段如“abcd”的数据,而且最后还有一个结束符’\0’。
  • 在C++中:

    • string有两种,要区别理解;

    • 第一种是字符串char[ ],例如’a’是char, “a”是char string,这两者都是普通的字符和字符串,和C语言中没什么不同值得注意的是后者包含两个字符,末尾有一个隐身的’\0’。

    • 第二种是封装好的字符串类,如string str = “a” 是C++ 封装好的string。

    • C++中的char string和string不是一回事。当用到了”string”这个关键词,就不是普通的字符串,而是用到了封装后的类。

    • 在C++中,char仍然是一个primitive type(原始类型),而string已经经过封装,成为了一个class(类)用到它时,我们需要 #include,它是C++ Standard Library (C++标准库)的一部分。

  • c中的char* 定义字符串,不能改变字符串内的字符的内容,但却可以把另外一个字符串赋给它。

2.1 String的基本概念

  • string是C++风格的字符串,而string本质是一个类
  • string和char *的区别
    • char *是一个指针
    • string是一个类,类内部封装了char * ,管理这个字符串,是一个char * 的容器
  • 特点:
    • string内部封装了很多成员方法
    • 例如:find查找、insert插入、delete删除、replace替换、copy拷贝
    • string管理char*的内存,不用担心复制越界和取值越界等,由类内部负责

2.2 String的构造函数

  • string(); //创建一个空的字符串,例如string str
  • string(const char* s); // 使用字符串s初始化
  • string(const string& str); // 使用一个string对象初始化另一个string对象
  • string(int n, char c); // 使用n个字符c初始化

2.3 Sring的赋值操作

  • string& operator = (const char* s); //char*类型字符串,赋值给当前字符串
  • string& operator = (const string &s); //把字符串s赋值给当前字符串
  • string& operator = (char c); //把字符赋值给当前字符串
  • string& assign(const char* s); //把字符串s赋值给当前字符串
  • string& assign(const char* s, int n); //把字符串s的前n位赋值给当前字符串
  • string& assign(const stringr &s); //把字符串s赋值给当前字符串
  • string& assign(int n, char c); //用n个字符赋值给当前字符串
//
//  main.cpp
//  String的赋值操作
//
//  Created by OnlyBei on 2021/9/24.
//

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

void test() {
    string s1;
    s1 = "hello,world";
    cout << "s1 = " << s1 << endl;
    
    string s2 = s1;
    cout << "s2 = " << s2 << endl;
    
    string s3;
    s3 = "a";
    cout << "s3 = " << s3 << endl;
    
    string s4;
    s4.assign("hello, c++");
    cout << "s4 = " << s4 << endl;
    
    string s5;
    s5.assign("hello, c++", 5);
    cout << "s5 = " << s5 << endl;
    
    string s6;
    s6.assign(s5);
    cout << "s6 = " << s6 << endl;
    
    string s7;
    s7.assign(15, 'h');
    cout << "s7 = " << s7 << endl;
}

int main(int argc, const char * argv[]) {
    // insert code here...
    test();
}

2.4 String字符串拼接

  • string& operator += (const char* str); // 重载+=操作符
  • string& operator += (const char c); // 重载+=操作符
  • string& operator += (const string& str); // 重载+=操作符
  • string& append(const char *s); // 把字符串s连接到当前字符串的结尾
  • string& append(const char *s,int n); // 把字符串s的前n位连接到当前字符串的结尾
  • string& append(const string &s); //同string& operator += (const char* str)
  • string& append(const string &s, int pos, int n); // 字符串s从pos开始的n个字符拼接到当前字符串的尾部

2.5 String字符串的查找

  • 功能描述
    • 查找:查找指定字符串是否存在
    • 替换:在指定的位置替换字符串
  • 函数原型:
    • int find(const string& str, int pos = 0) const; // 查找str第一次出现的位置,从pos开始查找
    • Int find(cosnt char* s, int pos = 0) const; // 查找s第一次出现的位置,从pos开始查找
    • int find(const char* s, int pos, int n) const; //从pos位置查找s的前n个字符第一次位置
    • int find(const char c, int pos = 0) const; // 查找字符c第一次出现位置
    • int rfind(const string& str, int pos = npos) const; // 查找str最后一次位置,从pos开始查找
    • int find(const char* s, int pos = npos) const; // 查找s最后一次出现位置,从pos开始查找
    • int rfind(const char* s, int pos, int n) const; //从pos查找s的前n个字符最后一次出现位置
    • int rfind(const char s, int pos = 0) const; //查找字符c最后一次出现位置
    • string& replace(int pos, int n , const string& str); //替换从pos开始n个字符位字符串str
    • string& replace(int pos, int n, const char* s); //替换从pos开始的n个字符为字符串

2.6 String字符串比较

  • 功能描述:

    • 字符串之间的比较
  • 比较方式:

    • 字符串比较是按字符的ASCII码进行对比
    • = 的话返回 0
    • >的话返回 1
    • <的话返回 -1
  • 函数原型:

    • int compare(const string &s) const; //与字符串s进行比较
    • int compare(const char *s) const; //与字符串s进行比较

2.7 String字符串的存取

  • string中单个字符的存取有两种方式
  • char& operator[] (int n); //通过[]方式取字符
  • Char& at(int n); //通过at方式取字符

修改的话直接,str[i] = “”; 或者 str.at(n) = “”;

2.8 String插入和删除

  • 功能描述:
    • 对string字符串进行插入和删除操作
  • 函数原型:
    • string& insert(int pos, const char* s); //插入字符串
    • string& insert(int pos, const string& s); //插入字符串
    • string& insert(int pos, int n, char c); //在指定位置插入n个字符串c
    • string& erase(int pos, int n = npos); //删除从pos开始的n个字符

2.9 String字符串子串

  • 功能描述:
    • 从字符串中获取想要的子串
  • 函数原型:
    • string substr(int pos = 0, int n = npos) const; // 返回从pos开始由n个字符组成的字符串

3. Vector容器

3.1 Vector基本概念

  • 功能:
    • vector数据结构和数组非常相似,也称为单端数组
  • vector与普通数组的区别
    • vector可以动态扩展
  • 动态扩展:
    • 并不是在原有空间之后拼接新空间,而是找更大的内存空间,然后将数据拷贝到新空间,释放原空间
  • vector容器迭代器是支持随机访问的一个迭代器

3.2 Vector容量和大小

  • 功能描述:
    • 对vector的容器的容量和大小进行操作
  • 函数原型
    • empty(); //判断容器是否为空
    • capacity(); //容器的容量
    • size(); //返回容器中元素的个数
    • resize(int num); //重新指定容器的大小为num,若容器变长,则以默认值填充新位置,若变短,则末尾超出容器元素被删除
    • resize(int num, in elem);//重新指定容器的大小为num,若容器变长,则以elem值填充新位置,若变短,则末尾超出容器元素被删除

3.3 Vector容器的插入和删除

  • push_back(); //尾插法
  • pop_back(); // 删除尾部的元素
  • clear(); //删除容器中所有元素
  • front(); // 返回容器中第一个元素
  • back(); // 返回容器中最后一个元素
  • swap(); //实现两个容器进行互换操作,实现内存收缩的效果
  • reverse(int len); //容器预留len个元素长度,预留位置不初始化,元素不可访问

4. deque容器

3.1 deque容器基本概念

  • 功能
    • 双端数组,可以对头端进行插入删除
  • deque的区别
    • vector对于头部的插入删除效率低、数据量越大、效率越低
    • deque相对而言,在头部进行数据插入删除的效率比vector高
    • vector访问元素的速度比deque快,这是由两者的内部实现有关

5. List容器

5.1 list基本概念

  • 功能
    • 将数据进行链式存储
    • 链表(list)是一种物理存储非连续的物理结构,数据元素的逻辑顺序是通过指针链接实现的
    • STL中的链表是一个双向循环链表

6.Set容器

  • set简介
    • 所有元素在插入时会自动排序
  • 本质
    • set/multiset属于关联式容器,底层用二叉树实现
  • set不允许用重复元素
  • multiset允许重复元素

7.Map容器

  • 简介:

    • map中所有元素都是pair(对组)
    • pair中第一个元素为key(键值),起到索引作用,第二个元素为value(元素)
    • 所有元素都会按照key值进行排序
  • 本质

    • map/multimap属于关联式容器,底层用二叉树实现
  • 优点:

    • 可以根据key值快速找到value值
  • 区别:

    • map不允许用重复元素
    • multimap允许重复元素

8. 谓词

8.1 谓词概念

  • 概念:
    • 返回布尔类型的仿函数称为谓词
    • 如果operator()接受一个参数,那么叫做一元谓词
    • 如果operator()接受两个参数,那么叫做二元谓词
//
//  main.cpp
//  谓词
//
//  Created by OnlyBei on 2021/9/25.
//

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

class getFive{
public:
    bool operator()(int val) { // 仿函数为什么这样写呢,可以看下面一段代码的源码
        return val > 5;
    }
};

void test() {
    vector<int> v;
    for(int i = 0; i < 10; i++) {
        v.push_back(i);
    }
    
    // getFive()是一个仿函数
    vector<int>::iterator it =  find_if(v.begin(), v.end(), getFive());
    
    if(it != v.end()) {
        cout << "找到了 " << *it << endl;
    }else {
        cout << "未找到" << endl;
    }
    
}

int main(int argc, const char * argv[]) {
    // insert code here...
    test();
}
find_if(_InputIterator __first, _InputIterator __last, _Predicate __pred)
{
    for (; __first != __last; ++__first)
        if (__pred(*__first)) // 如果这个为真,则跳出循环,放回一个迭代器
            break;
    return __first; 
}
  • 二元谓词

    //
    //  main.cpp
    //  谓词
    //
    //  Created by OnlyBei on 2021/9/25.
    //
    
    #include <iostream>
    #include <vector>
    #include <algorithm>
    using namespace std;
    
    class FuncSort {
    public:
        bool operator() (int a, int b) {
            return a > b;
        }
    };
    
    void test02() {
        vector<int> v1;
        v1.push_back(10);
        v1.push_back(30);
        v1.push_back(80);
        v1.push_back(50);
        v1.push_back(20);
        
    //    sort(v1.begin(), v1.end()); // 默认从小打大
        sort(v1.begin(), v1.end(), FuncSort());
        
        for(vector<int>::iterator it = v1.begin(); it != v1.end(); it++) {
            cout << *it << " ";
        }
        cout << endl;
    
    }
    
    int main(int argc, const char * argv[]) {
        test02();
    }
    
------------- 本文结束 感谢阅读 -------------