• C/C++基础


    C/C++基础

    转自:http://blog.csdn.net/fangbaolei2088/article/details/7990519

    1.编译器g++
    g++ -c 只编译不连接,生成.o文件
    g++ -o 修改编译后生成的文件的名字(默认为a.out)


    2.C++优点
    Supporting data abstraction
    Object-oriented
    Contains all C features
    Portable and efficient as C
    Can be linked to existing C libraries and functions(!!)
    ...


    3.变量名
    第一个字母必须是字母或下划线
    只能使用字母或下划线或数字
    中间不能有空格
    不能是保留字,不能与库函数重名
    区分大小写


    4.基本数据类型
    char=> unsigned/signed char
    int=> unsigned/signed long/short int
    float=> double, long double
    bool


    5.四个类型转换算子(详细见后面)
    static_cast: 
    const_cast:
    reinterpret_cast:
    dynamic_cast:


    6.运算符
    优先级前三名:() .或-> 单目
    优先级后三名: ?: = 逗号


    7.枚举类型
    enum color{RED, BLUE=10, GREEN}; // 默认数值为0, 1, 2...这样改变值后为0, 10, 11...
    color c = GREEN;


    8.表达式(略)


    9.控制语句
    if(){}else{}
    while(){}
    do{}while();
    for(){}
    switch(){case;}


    10.函数
    函数三要素:返回类型、函数名、参数表
    声明(无函数体;参数表参数可无参数名,但必须有类型)
    定义(有函数体{})
    调用函数实际是利用栈操作,执行完一个函数时候,栈释放
    使用默认参数(必须从右至左指定默认值)


    11.内联函数(inline)
    编译时,只是将内联函数的代码粘贴到调用处,不进行栈操作,所以速度快
    必须声明与定义放一起
    不支持控制语句(所以实际中inline函数很少使用)


    12.递归函数
    函数调用自己
    必须有结束条件
    栈操作


    13.函数重载(overload)
    重载函数至少在参数个数、类型、顺序上有所不同
    尽量不要使用默认参数的函数,防止调用冲突


    14.函数参数的const限定
    可以防止在函数中修改某个传入参数的值


    15.变量的作用域与可见性(☆)
    局部变量:存于栈;函数调用完释放;作用域本函数内部
    全局变量:存于全局数据区;程序结束释放;作用域本源文件、其他源文件使用时加extern声明
    static局部变量:存于全局数据区;只在第一次调用函数时初始化一次;作用域本函数内部
    static全局变量:存于全局数据区;程序结束释放;可见范围本源文件(其他源文件不可见)


    16.头文件(.h)
    声明函数
    struct
    class
    enum
    extern声明变量(使用其他源文件的全局变量)


    17.进程空间
    Data
    Heap
    Code
    Stack


    18.数组
    只声明不初始化时,必须有元素个数
    花括号初始化必须与声明放一起(花括号初始化时,元素个数可以省去)
    花括号后的分号注意
    字符数组初始化可用双引号
    好习惯:memset(buf, 0x00, sizeof(buf)); //使用数组、结构时均可如此初始化内存


    19.结构(struct)
    用结构定义的结构名可以当成一种新数据类型使用

    如:
    struct Person{...;};
    Person p1; // It's correct
    struct Person p2; // It's correct too

    注意定义结构时候最后的分号!!
    结构之间可赋值
    占用内存空间(Unix/windows下自然对界,结构大小必为最大成员的整数倍;Linux下只需整体补齐为int的整数倍)


    20.指针
    为防止野指针,一般声明指针时最好立即赋值(NULL)

    注意*号的使用:
    声明时:int* pi = NULL; // 此处星号表示变量pi为指针类型变量
    赋值时:pi = &i; // 此处直接使用pi,pi变量存储的是地址0x...
    使用时:*pi = 5; // 此处星号表示指针所指向的变量i,此语句等同于 i = 5;


    21.结构取成员
    结构变量取成员:p.id
    指向结构的指针取成员:pp->id 或 (*pp).id


    22.数组名其实是常量指针(不可进行自加减)


    23.字符串操作(#i nclude )
    strcpy(target, source);
    strlen();
    strcmp(target, source); //相同返回0
    strncmp(target, source, n); //比较n个字符
    strcat(target, source);


    24.C风格字符串与C++风格字符串
    C style string: char* or char []
    C++ style string: string
    (!!!注意:Unix C中,大部分库函数和系统函数还是使用C风格字符串)
    这两种字符串可以相互转化:
    C style to C++ style: string a = b;
    C++ style to C style: char* b = a.c_str(); // 使用了c_str()函数,或使用data()函数


    25.使用堆空间(heap)进行动态内存分配
    int* p = new int[10];
    delete[] p; // 只是释放p指向的内存,释放后的内存其他程序可以使用,否则内存泄漏
    p = NULL; //将p指针赋为空,防止野指针


    26.函数指针
    !!!注意:函数指针是一个变量,不是一个函数

    如:
    void (*pf)(int, int); //pf是一个指针变量,只能指向void f(int, int)类的函数!!!
    void f(int a, int b){...}
    pf = f; //将f的首地址存入pf变量中!!!

    函数指针一般只是用来声明函数的参数时使用
    (即函数fa需要调用另一个函数fb时,将fb的函数指针放入声明fa的参数列表中)

    如:
    int fa(int a, void (*pf)(int, int)){...} //调用函数fa时,只能在第二个参数中传入一个类型为指向void f(int, int)函数的指针
    void fb(int a, int b){...}
    void (*pf)(int, int) = fb;
    fa(5, pf);


    27.void指针
    一般作为函数声明时的函数参数,可增加函数通用性
    不可进行自加减运算


    28.常量指针指针常量
    常量指针:const int* p; //p指向的数据不可变(p指向常量)
    指针常量:int* const p; //p不可变(必须初始化)


    29.引用
    引用是一个变量的别名
    声明:int& ri = i;
    使用:ri = 5; //相当于使用i本身(i=5)
    常用来做函数参数传递


    30.typedef给类型起别名
    步骤:
    声明一个变量或函数
    把名字改为别名
    前加typedef

    ★C++面向对象特性


    1.类
    封装了函数成员的struct
    (其实在C++中,struct内部也可以封装函数,但习惯上struct只封装数据,class可以封装数据和函数)
    增加成员访问权限(public, private, protected)
    类默认的是private(struct默认为public)
    private=> 只能被本类或者友元访问
    protected=> 只能被本类或者友元或者子类访问
    public=>全部公开
    外部定义类的成员函数用域作用符(::)
    注意分号!!


    2.构造函数(constructor)
    创建对象时起初始化对象的作用
    名字与类同
    只能为public!!
    无返回类型!!
    可重载!!
    没有时系统自动添加(一旦自己定义,系统不再添加)
    可用冒号(:)引出初始化列表,如:
    Person::Person(int a, int b):id(a), age(b){} //将成员id赋值为a, 将成员age赋值为b
    struct也可以使用构造函数


    3.拷贝构造函数(copy constructor)
    系统默认存在一个拷贝构造函数,对成员依次拷贝(浅拷贝),有指针成员时危险
    用一个已有对象对同类其他对象进行初始化
    Person(const Person& pa);
    使用:Person p2(p1); //相当于将p1所有成员赋值给p2


    4.析构函数(destructor)
    ~类名(){}
    无返回类型!!
    不可重载!!
    无参数!!
    系统自动调用
    做清理工作


    5.继承
    继承方式public, protected, private
    class Derived:public Base{};
    子类继承父类的所有成员,但是不能访问父类的private成员
    public继承来的成员属性不变
    protected继承来的成员public变为protected,其他不变
    private继承来的全部变为private

    继承中的构造函数,系统先调用父类再调用子类
    子类
    的构造函数可以给父类的构造函数传递参数,如:
    Person::Person(int a, int b):id(a), age(b){}
    Student::Student(int a, int b, int c):Person(a, b), grade(c){} //给父类的构造函数传递参数a, b

    继承中的析构函数,系统先调用子类再调用父类

    覆盖:子类中的函数会覆盖父类中的同名函数


    6.多态与虚函数
    为解决覆盖问题,将父类的函数声明为virtual型(虚函数),子类中再定义同名的函数
    则使用指向父类指针指向子类对象时,调用该函数时,可自动识别对象类型,调用相应的子类中的函数
    如:
    virtual void Person::display(){cout << "Person" << endl;} //声明为virtual函数
    void Student::display(){cout << "Student" << endl;}
    Person* p = new Student;
    p->display(); //调用子类的display
    显示为“Student”


    7.纯虚函数
    若要父类的函数为空,只为了使用多态时,可以声明为纯虚函数
    virtual void display() = 0;


    8.多重继承与虚继承(菱形继承)(不常用)


    9.类型转换算子详解
    static_cast:void指针与其他类型指针间转换
    const_cast:常量与变量之间转换
    reinterpret_cast:指针与整型数据之间转换;任意类型指针之间转换
    dynamic_cast:用于有继承关系且有虚函数的类之间的转换,子转父才能成功
    格式:xxxx_cast(data)


    10.抽象数据类型ADT
    抽象类不能创建对象


    11.友元(friend)
    授权本类外部的函数或其他类可以使用本类的所有成员(包括private成员),使用时要用“对象.xxxx”


    12.常量成员函数
    类的成员函数参数列表后加上const,表示本函数为常量成员函数,不能修改本类的成员,如:
    void display()const{} //display中不能修改本类的成员数据


    13.静态成员
    静态数据成员:所有对象使用一份数据;初始化放类外边(::);访问也用(::)
    静态函数成员:相当于全局函数;只能访问静态数据成员;定义放类外边(::);访问用(::)


    14.运算符重载
    将“operator...”看成函数名,进行定义
    返回类型不能为空!!
    方法:成员或友元(尽量成员)
    不能改变运算符的操作数(括号例外,括号的操作数特殊)
    不能重载的运算符: . .* :: ?: sizeof # ##
    操作基本类型的运算符不能重载(即运算符的操作数中至少应该有一个是自定义类型,如类)

    只能用成员函数重载的:operator= operator[] operator() operator-> operator->*
    成员函数重载时,默认的第一个操作数总是对象本身!!!所以参数列表的第一个操作数可以省去!!!

    只能用友元函数重载的:operator<< operator>>
    当第一个操作数非对象本身时,应使用友元!!!

    下面详细介绍几个运算符的重载:

    ▲operator=
    当类没有自定义operator=时,编译器自动生成一个,有指针成员时候危险
    只能成员函数重载
    常用格式:
    A& operator=(const A& ao)
    {
    if (this == &ao) return *this; //判断this指针是否指向ao对象的地址
    ...=...;
    *..=*..; //指针成员赋值其指向的变量
    return *this;
    }

    ▲operator++() and operator++(int) 前加与后加
    定义这两个函数后,使用++a时调用前者,使用a++时调用后者
    哑元区分
    前加加的格式:
    A& operator++() //使用引用
    {
    ...++;
    ...++;
    return *this;
    }
    后加加的格式:
    A operator++(int dummy) //不能使用引用
    {
    A temp = *this;
    ...++;
    ...++;
    return temp; //返回自加之前的值
    }

    ▲双目运算符
    作为成员函数重载时,第一个操作数必须是对象本身,且在参数列表中可以省去!!
    当第一个操作数非对象本身时,应用友元法!!

    ▲operator()
    特殊,操作数的个数不确定
    使用时候类似函数,称为functor(仿函数),实际功能比函数还要强大

    ▲operator new/delete
    较特殊,格式固定
    static void* operator new(size_t sz){} //必须是static,返回void*
    static void operator delete(void*){}
    new和delete可同时带上[]

    ▲转换运算符
    用于将一个对象转换为其他的数据类型
    格式较特殊,不写返回类型(其类型名即为返回类型)
    如:
    operator double(){} //将返回double类型变量
    使用:
    double(ao);

    ▲operator<< and operator>>
    这两个流操作符必须作为友元重载
    格式较固定:
    ostream& operator<< (ostream& o, A& ao)
    {
    o << .... << .... << ....;
    return o;
    }

    istream& operator>> (istream& i, A& ao)
    {
    i >> .... >> .... >> ....;
    return i;
    }

    15.main命令行参数模式
    int main(int argc, char* argv[])
    //argc指命令行参数的个数,包括命令本身
    //argv存储了每个参数,包括命令本身即argv[0]
    //argv为char*[]型,即char**型,或char[][]型,相当于二维字符数组或一维字符串数组

    16.I/O标准流
    (cin, cout, cerr, clog)
    cin和cout支持缓冲,支持重定向
    cerr为错误信息输出,不支持缓冲,不支持重定向
    clog为日志输出,不支持重定向

    cin详解:
    cin >> //可连续使用;以空白(包括空格、回车、TAB)为分隔符
    cin.get(char c) //可连续使用;获取任意单个字符,包括空白
    cin.getline(char* buf, sizeof(buf), ' ') //可连续使用;获取一行,到最后指定的字符结束,可包括空白,默认回车
    cin.gcount() //计数
    cin.read(char* buf, sizeof(buf)) //可连续使用;读取指定大小的内容,包括空白;第一个参数必须为char*,可用强制转换
    cin.ignore(1000, ' ') //忽略指定大小的内容,到制定字符结束忽略;常用来清空缓冲区
    cin.clear() //清楚错误状态;常后跟ignore
    if(!cin) //判断是否出错;cin为false则出错
    cin.peek() //查看缓冲区下一个字符,但是不读取,即用get时候还可以读到
    cin.putback() //将上一个读回的字符返回缓冲区,不常用

    cout详解:
    cout <<
    控制符:endl, flush ....
    cout.put(char)
    cout.width(int) //一次性命令
    cout.fill(char)
    cout.precision(int)
    cout.setf(ios::...)
    cout.unsetf(ios::...)
    (cout这些命令不常用,常用头文件中的函数代替)

    :
    setw(int) //设置宽度
    setfill(char) //设置填充字符
    setprecision(int) //设置精度,单用时表示总位数;与fixed连用时表示小数点后的位数

    17.I/O文件流
    (需包含头文件)

    ifstream类:
    使用:ifstream fin; //创建一个对象fin
    cin中可以使用的函数在fin中同样可以使用
    对cin的扩展:
    构造函数可以制定文件名及打开方式
    fin.open(...)
    fin.read(...) //较多的使用此函数读取
    fin.is_open() //检查是否打开成功,事实上经常用 if (!fin) 代替此函数
    fin.eof() //判断是否超过文件末尾;超过末尾才返回true
    fin.close() //关闭文件

    ofstream类:
    使用:ofstream fout;
    常用打开方式有:ios::binary ios::app ios::out
    (其余同上)


    常用写/读格式:
    fout.write((char*)&a, sizeof(a)); //将a对象的数据写入文件;注意强制类型转换(char*)
    fin.read((char*)&b, sizeof(b)); //将文件中的内容读入到b对象的空间

    18.异常(exception)
    (#i nclude )
    try
    {
    ....;
    if (....)
    {
    throw ....;
    ....; //不会执行此句
    }
    }
    catch(....)
    {
    ....;
    }

    注意:
    catch捕获的异常为与throw同类型的数据
    捕获异常后,程序在catch处理完异常后的地方继续执行,不会返回throw处
    产生异常后,程序立即跳转,不会执行throw下的语句
    如果没有catch捕获已经抛出的异常,最终内核捕捉到异常会将程序强制不正常关闭
    catch(...)(括号中三个点)可以捕捉任何类型异常
    异常的类型常使用内部类(inner class)来定义

    19.内部类
    内部类属于它所在的类的类成员(即类的静态成员),不属于某个对象
    内部类的数据和它所在的类的数据互不相通

    ★数据结构


    1.链表(LinkList)
    由节点(node)构成,每个节点可以为一个struct,且该struct里可以封装进构造、析构等函数(而且常常如此)
    每个节点可以如下定义:
    struct Node
    {
    DATA data; // ADT
    Node* next; //指向下一个节点的指针
    Node(const DATA d) //构造函数初始化节点
    {
    data = d;
    next = NULL;
    }
    };

    每个链表由一个头指针head(Node* head;)进行访问

    基本操作:增、删、查、改

    ▲插入节点(增):
    Node* p = new Node; //分配新节点的空间
    p->data = 0; p->next = NULL; //初始化新节点(此两句可以封装到Node的构造函数中)
    //寻找要插入位置(即前一个Node的next指向的地址,假设为lp)
    p->next = lp; //把新节点的next指向要插入位置的下一个节点
    lp = p; //插入位置的前一个Node的next指向新节点
    //插入成功

    ▲删除节点(删):
    Node* temp = p->next; //将要删除节点的next指针(即p的下一个节点的地址)保存
    delete p; //删除p的空间
    lp = temp; //p节点的前一个节点的next指向p的下一个节点
    //删除成功

    ▲查找节点(查):
    Node* p = head; //从头指针开始遍历
    while (p) //p不为NULL,就继续遍历
    {
    if (p->data == finddata) break;
    p = p->next;
    }
    //缺点:如此查找到的p,只是在值上等于p前一个节点的next的值,而并非其前一个节点的next本身!!!
    //想要得到前一个节点的next本身也很简单,只需要再定义一个指针,遍历时使该指针滞后一步
    //如:
    Node* p = head;
    Node* lp = NULL; //总是滞后p一步
    while (p)
    {
    if (p->data == finddata) break;
    lp = p;
    p = p->next;
    }
    //这样得到的lp就是p前一个节点的指针,lp->next和p的值应该相等,且lp->next是链表中的数据本身!!

    ▲修改节点(改):略

    ▲删除全部节点:
    总是删除头节点的方法
    Node* p = head;
    while (p)
    {
    p = head->next; //将头节点的下一个节点的地址保存起来
    delete head;
    head = p;
    }
    //删除完成

    ▲operator[]:略


    2.栈(stack)
    LIFO(last in first out)
    常用操作:push(), pop(), isempty(), clear()
    (实际使用时,弹栈操作总是分离pop的功能为top和pop两个,top只管访问,pop只管删除)
    可以用数组或链表实现
    数组:下标
    链表:前插前取


    3.队列(queue)
    FIFO(first in first out)
    可以用数组或链表实现
    数组:下标
    链表:后插前取
    优先队列(priority queue):插入时自动排序


    4.二叉树(binary tree)
    集数组和链表的优点:可以快速查找(数组);可以方便插入数据(链表)
    每个节点最多有两个子节点
    所以每个节点包含两个节点指针left和right
    struct bNode
    {
    DATA data;
    bNode* left;
    bNode* right;
    bNode(const DATA d) //constructor
    {
    data = d;
    left = NULL;
    right = NULL;
    }
    };

    通过一个指向根节点root的指针(bNode* root;)访问
    一般通过递归实现操作!!


    5.二叉查找树(binary search tree)
    左子节点(包括子节点的子节点)一定小于父节点
    右子节点(包括子节点的子节点)一点大于或等于父节点

    常用操作:增、遍历、删、查、改
    一般均用递归法实现!!

    ▲插入节点(增):
    void insert(bNode*& ptr, bNode* pnew) //ptr为树的待插入位置(必须使用指针的引用!!),pnew为待插入节点
    {
    if (ptr == NULL) //当树为空时;实为递归出口!!
    {
    ptr = pnew;
    }
    else if (pnew->data < ptr->data) //插入数据比该位置的数据小的时候,往左侧插入
    {
    insert(ptr->left); //递归调用
    }
    else //插入数据比该位置的数据大于或等于的时候,往右侧插入
    {
    insert(ptr->right); //递归调用
    }
    }
    //插入成功


    ▲遍历:
    void visit(bNode* ptr) //待遍历节点的指针,第一次调用时传入root指针
    {
    if (ptr == NULL) return; //递归出口
    visit(ptr->left); //递归调用,遍历左侧
    cout << ptr->data << endl; //输出本节点的内容
    visit(ptr->right); //递归调用,遍历右侧
    }
    //遍历完成


    ▲清空二叉树:
    void clear(bNode*& ptr) //待清空的节点的指针(必须使用指针的引用!!),第一次调用时传入root指针
    {
    if (ptr == NULL) return;
    clear(ptr->left);
    clear(ptr->right);
    delete ptr;
    ptr = NULL;
    }
    //清空成功


    ▲删除一个节点(删):
    删除二叉查找树的一个节点较麻烦,常用方法有两种:降级法和替换法

    降级法:将删除的节点的左子树挂入其右子树下边
    替换法:将删除的机电的左子树下面最大的节点替换掉删除的节点

    降级法实现代码:
    void deleteNode(bNode*& ptr) //待删除的节点的指针的引用!!
    {
    bNode* p = ptr; //先将该节点的地址保存,以备后用
    insert(ptr->left, ptr->right); //将左子树挂到右子树下面(参考insert函数)
    ptr = ptr->right;
    delete p; //删除节点的空间,用到刚才保存地址的p,因为此时ptr已经改变
    }
    //删除完成

    替换法实现代码:
    先写查找左子树下边最大节点的函数:
    bNode*& findmax(bNode*& ptr) //返回类型必须为引用!!!
    {
    if (ptr->right == NULL) return ptr; //递归出口
    findmax(ptr->right);
    }
    void deleteNode(bNode*& ptr)
    {
    bNode* p = ptr;
    bNode*& pmaxref = findmax(ptr->left); //此处也必须使用引用!!!
    bNode* pmax = pmaxref; //将pmaxref指向的节点的地址保存到pmax
    pmaxref = NULL; //将左子树最大节点从树上摘下!!注意,操作的是引用!!!
    ptr = pmax; //将要删除的节点的位置改为左子树最大节点;注意,操作的ptr为引用!!!
    pmax->left = p->left;
    pmax->right = p->right;
    }
    //删除完成

    ▲修改一个节点(改):先删除再插入

    6.算法(algorithm)
    算法分析、效率、时间复杂度、空间复杂度
    大O表示法(Big O Notation):最多多少次
    算法设计策略:蛮力法、递归法、贪心法等
    查找:线性查找、二分法查找、索引查找
    排序:选择排序、插入排序、冒泡排序、快速排序、希尔排序

    排序方法详解:(按降序为例)

    ▲选择排序:
    思路:第一轮排序将所有元素中最大的放在第一个,然后下一轮排序将剩余元素中最大的放到剩余元素的第一个,然后......
    方法:双循环或递归

    ▲插入排序:
    思路:认为第一个元素已经排好序,然后看下一个元素,如果比第一个大则排到其前边,否则排后边,依次下去......
    实现起来较复杂

    ▲冒泡排序:
    思路:每轮只比较相邻元素大小,前小后大则交换位置,这样比较多轮以后,直到不再发生任何交换时,排序结束
    最慢的排序方法

    ▲快速排序:
    思路:选出一个分界值(pivot),将大于分界值的移到左侧,小于分界值的移到右侧,一般可以使用递归
    具体实现方法多种

    ▲库函数中的快速排序:(#i nclude ) (qsort)
    qsort(int*, length, sizeof(int), (*compare));
    //参数表依次为待排序的数组首地址、数组长度、数组的元素大小、比较函数的首地址
    //比较函数需要自己定义

    ★自定义模板与标准模板库

    1.自定义模板
    使用模板是为了泛型编程
    分为函数模板和类模板
    定义模板时:
    template //模板头;typename关键字可用class代替
    ...{} //函数体或类体中,可以将符号T当成一种数据类型

    使用模板时:

    函数模板可以根据传入参数的类型,自动识别类型
    类模板需要将参数用尖括号传递:vector vi;

    2.标准模板库(STL)
    标准模板库包含以下内容:
    container(容器)
    algorithm(算法)
    iterator(迭代器)
    functor(仿函数)
    adapter(容器配接器)
    allocator(分配器)


    3.container(容器)
    用于存放一系列数据
    分为Sequence Container和Associative Container两种
    (序列式容器和关联式容器)

    所有容器的共性:

    都有三种构造函数(无参、拷贝、区间)
    支持运算符:赋值(=)、比较(< <= > >= == !=)
    支持交换函数swap(),对两个容器进行交换(s1.swap(s2);)
    支持的操作:insert, erase, clear, empty(判断非空), size
    都有四种迭代器:iterator, reverse_iterator, const_iterator, const_reverse_iterator
    迭代器相关函数:begin, end, rbegin, rend


    4.iterator(迭代器)
    迭代器是一个容器的内部类,只封装了一个指针
    外部访问容器的元素时,可以通过迭代器访问,所以迭代器的作用就是智能指针
    迭代器内部重载的运算符一般有星号(*)、不等于(!=)、自加(++)、自减(--)四个运算符

    迭代器与其所在的类的桥梁是一些迭代器相关函数(begin,end,rbegin,rend)等,带r的是反向

    使用方法:

    类名::iterator it; //声明一个迭代器对象
    for (it=对象.begin; it!=对象.end; it++) {...} //以此来遍历一个容器


    5.Sequence Container(序列式容器)
    包括三种:vector, deque, list

    ▲序列式容器的共性:
    构造函数可以指定个数及初始值
    增加了resize(len)或resize(len, fillVal)
    增加了insert(position, num, data)
    增加了assign(num, data)
    增加了取首尾函数:front(), back() (返回引用)
    增加了后增删函数:push_back(data), pop_back()


    ▲vector:(#i nclude )
    vector其实就是一个动态数组
    支持[] (不检查越界)
    支持at() (越界抛异常)
    增加了capacity()函数 (容量)(有时!=size())
    增加了reserve(len)函数 (调整容量)
    用后插后取时效率较高


    ▲deque:(#i nclude )
    deque其实是vector的增强版
    增加了前增删函数:push_front(data), pop_front()
    比vector减少了capacity和reserve函数


    ▲list:(#i nclude)
    list其实是一个双向链表
    不支持 [] 和 at()
    只支持双向迭代器(++ --),不支持随机迭代器(+n -n)
    增加了remove(data)(删除所有data节点)
    增加了sort()(升序排序)
    增加了reverse()(颠倒顺序)
    增加了unique()(去掉相邻的重复元素,变为一个)
    增加了merge(list2)(将list2保序合并到当前的list,list2变空,合并后排好序)
    增加了splice(it, list2, list2.it1, list2.it2)(将list2中的区间转移到当前list的指定位置)
    list适用于元素频繁插入删除的时候使用


    6.Associative Container(关联式容器)
    包括两种:map/multimap, set/multiset

    ▲关联式容器的共性:
    实质为二叉查找树
    可自动排序(要求容器元素的类型必须支持小于运算符)
    每个元素都有一个key值
    增加了insert(data)(不需指定位置)
    增加了find(key)(返回第一个;若查不到,返回end())
    增加了erase(key)(删除所有关键字为key的元素)
    增加了count(key)
    增加了lower_bound(key), upper_bound(key)
    增加了equal_range(key)


    ▲map/multimap:(#i nclude


    ▲map/multimap插入元素方法:
    插入对有四种方法:
    insert(map::value_type("ABC", 100));
    insert(pair("ABC", 100));
    insert(make_pair("ABC", 100));
    ["ABC"] = 100;
    (上述"ABC"为key, 100为value)
    (注意:value_type为map类内部的函数)
    (注意:pair为标准模板库中的一个类模板,其元素为first, second)
    (注意:make_pair为标准库函数中的函数)
    (注意:方括号运算符小心使用:若"ABC"不存在,则插入新的;若"ABC"已存在,在map中修改,在multimap中仍然插入新的)


    ▲set/multiset:(#i nclude )
    每个元素只由一个key组成
    set与multiset区别:同上

    7.adapter(容器配接器)
    #i nclude ==> stack
    #i nclude ==> queue pqueue

    使用:push(), pop, size(), empty()


    8.algorithm(算法)
    #i nclude ==> for_each find sort copy replace
    #i nclude ==> min max accumulate swap

  • 相关阅读:
    HDU 2414 Chessboard Dance(模拟题,仅此纪念我的堕落)
    poj 1625 (AC自动机好模版,大数好模版)
    HDU 1907 John(博弈)
    如何创建一个.NET Core项目
    C#中的委托
    WEB开发者必备的7个JavaScript函数
    带你进入Angular js的大门
    程序猿的年终总结,各种版本各种残
    ASP.NET 开发人员不必担心 Node 的五大理由
    7 个 jQuery 最佳实践
  • 原文地址:https://www.cnblogs.com/harry335/p/4554304.html
Copyright © 2020-2023  润新知