C++基础知识七

一、STL
list是一个双向链表容器,可以高效的进行插入和删除。list不可以随机存取元素,所以不支持at()和[]操作符。

#include <iostream>
#include <list>
#include <cstring>

using namespace std;

class Student
{
    
    
    private:
        int id;
        char name[32];
    public:
        Student();
        Student(int i,char *n);
        void show();
};

Student::Student(int i, char *n)
{
    
    
    id = i;
    strcpy(name,n);
}

void Student::show()
{
    
    
    cout<<"id = "<<id<<"name = "<<name<<endl;
}

int main(int argc, char const *argv[])
{
    
    
    Student s1(1,"aaa");  
    Student s2(2,"bbb");
    Student s3(3,"ccc");
    Student s4(4,"ddd");
    Student s5(5,"eee");
    Student s6(6,"fff");

    list<Student> S;   //创建链表对象
    S.push_back(s1);   // 尾插法
    S.push_back(s2);
    S.push_back(s3);
    S.push_back(s4);

    S.push_front(s5);  //头插法
    S.push_front(s6);

    for(list<Student>::iterator it = S.begin(); it != S.end(); it++)
    {
    
    
        it->show();
    }

    S.pop_back();  //删除最后一个结点
    S.pop_front(); //删除第一个结点

    cout<<"___________________________"<<endl;

    for(list<Student>::iterator it = S.begin(); it != S.end(); it++)
    {
    
    
        it->show();
    }

    cout<<"第一个元素是:"<<endl;
    S.front().show();

    cout<<"最后一个元素是:"<<endl;
    S.back().show();

    cout<<"链表的长度是:"<<endl;
    cout<<S.size()<<endl;
    //cout<<

    cout<<"链表扩充"<<endl;
    S.resize(5,s6);
    for(list<Student>::iterator it = S.begin(); it != S.end(); it++)
    {
    
    
        it->show();
    }

    //对象数组
    cout<<"------------------------"<<endl;
    Student s[5] = {
    
    Student{
    
    10,"a"},Student{
    
    11,"b"},Student{
    
    12,"c"},Student{
    
    13,"d"},Student{
    
    14,"e"}};
    S.insert(S.begin(),s[3]);
    for(list<Student>::iterator it = S.begin(); it != S.end(); it++)
    {
    
    
        it->show();
    }

    cout<<"-------------------"<<endl;
    S.insert(S.end(),5,s[4]);    //尾部插入5个s[4]
    for(list<Student>::iterator it = S.begin(); it != S.end(); it++)
    {
    
    
        it->show();
    }

    cout<<"-----------------"<<endl;
    S.insert(S.end(),s,s+3);   //在链表尾部插入一个区间
    for(list<Student>::iterator it = S.begin(); it != S.end(); it++)
    {
    
    
        it->show();
    }

    cout<<"删除一个区间"<<endl;
    list<Student>::iterator it = S.begin();
    for(int i = 0; i < 5; i++)
    {
    
    
        it++;
    }
    S.erase(it,S.end());
    for(list<Student>::iterator it = S.begin(); it != S.end(); it++)
    {
    
    
        it->show();
    }

    cout<<"删除一个位置"<<endl;
    S.erase(S.begin());    //删除第一个位置
    for(list<Student>::iterator it = S.begin(); it != S.end(); it++)
    {
    
    
        it->show();
    }

    cout<<"链表反转"<<endl;
    S.reverse();
    for(list<Student>::iterator it = S.begin(); it != S.end(); it++)
    {
    
    
        it->show();
    }

    return 0;


}

1.2 栈
栈是先进后出

#include <iostream>
#include <stack>

using namespace std;

int main(int argc, char const *argv[])
{
    
    
    stack<int> s;
    srand(time(NULL));
    int num;

    for(int i = 0; i < 10; i++)
    {
    
    
        num = rand() % 10;
        s.push(num);  //进栈
        cout<<num<<"    进栈成功"<<endl;
    }

    cout<<"栈顶元素"<<s.top()<<endl;
    cout<<"栈的大小"<<s.size()<<endl;

    //栈和队列不存在遍历,所以没有迭代器
    while(!s.empty())
    {
    
    
        cout<<s.top()<<"   出栈 "<<endl;
        s.pop();
    }


    return 0;
}

1.3 队列

#include <iostream>
#include <queue>

using namespace std;

int main(int argc, char const *argv[])
{
    
    
    queue<int> q;
    for(int i = 0; i < 10; i++)
    {
    
    
        q.push(i);
        cout<<i<<"   入队成功"<<endl;
    }

    cout<<"队头元素:"<<q.front()<<endl;
    cout<<"队尾元素:"<<q.back()<<endl;
    cout<<"队列大小:"<<q.size()<<endl;

    while(!q.empty())
    {
    
    
        cout<<q.front()<<" 出队"<<endl;
        q.pop();
    }

    return 0;
}

1.4 优先队列

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

int main(int argc, char const *argv[])
{
    
    
    //priority_queue<int> p;
    //priority_queue<int, vector<int>, less<int>> p;  //等价于priority_queue<int> p;
    priority_queue<int, vector<int>, greater<int>> p;
    srand(time(NULL));
    int num;
    
    for(int i = 0; i < 10; i++)
    {
    
    
        num = rand() % 10;
        p.push(num);
        cout<<"  入队成功"<<endl;
    }

    cout<<"队头元素:"<<p.top()<<endl;
    cout<<"队列大小:"<<p.size()<<endl;

    while(!p.empty())
    {
    
    
        cout<<p.top()<<" 出队"<<endl;
        p.pop();
    }

    return 0;
}

1.4 函数对象
函数指针被广泛的用于回调函数的实现,C++提供了另一种回调函数的实现方式,就是函数对象。
函数对象:又称为伪函数,实质是重载了()运算符,进而操作普通类对象,从语法上来说,和普通函数行为类似
greater 和 less就是函数对象

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

class Student
{
    
    
    friend class Compare;
    private:
        int id;
        string name;
    public:
        Student(int i,string n)
        {
    
    
            id = i;
            name = n;
        }

        void show()const
        {
    
    
            cout<<"id = "<<id<<" name = "<< name<<endl; 
        }

        bool operator<(const Student &s) const
        {
    
    
            return this->id < s.id;
        }
};

class Compare
{
    
    
    public:
        bool operator()(const Student &s1, const Student &s2) const
        {
    
    
            return s1.id > s2.id;
        }
};


int main(int argc, char const *argv[])
{
    
    
    
    Student s1(1, "ff");
    Student s2(4, "zz");
    Student s3(3, "aa");
    Student s4(9, "qq");
    Student s5(0, "rr");
    Student s6(3, "yy");
    Student s7(7, "uu");
    Student s8(1, "pp");
    Student s9(2, "mm");

    priority_queue<Student,vector<Student>,Compare> S;
    S.push(s1);
    S.push(s2);
    S.push(s3);
    S.push(s4);
    S.push(s5);
    S.push(s6);
    S.push(s7);
    S.push(s8);
    S.push(s9);

    while(!S.empty())
    {
    
    
        S.top().show();
        S.pop();
    }

    Compare c;    //函数对象  伪函数
    c(s1,s2);   //c.operator()(s2,s2);

    return 0;
}

1.6 set
set是一个集合容器,其中包括的元素是唯一的,集合中的元素按一定的顺序排列,元素的插入过程是顺序排列的,所以不能指定位置插入
set是采用红黑树变体的数据结构实现,红黑树属于平衡二叉树,在插入和删除操作上比vector快。
set不可以直接存取元素(at()与[]操作符)
multiset和set:set支持唯一的键值,而multiset支持同一键值出现多次。
不可以直接修改set和multiset容器中的元素值,因为该类容器是自动排序的,如果希望修改一个元素的值,必须先删除原有的元素,再插入新的元素。

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

class Student
{
    
    
    private:
        int id;
        string name;
    public:
        Student(int i,string n)
        {
    
    
            id = i;
            name = n;
        }

        void show()const
        {
    
    
            cout<<"id = "<<id<<" name = "<< name<<endl; 
        }

        bool operator<(const Student &s) const
        {
    
    
            return this->id < s.id;
        }
        bool operator>(const Student &s) const
        {
    
    
            return this->id > s.id;
        }
};


int main(int argc, char const *argv[])
{
    
    
    Student s1(1, "ff");
    Student s2(4, "zz");
    Student s3(3, "aa");
    Student s4(9, "qq");
    Student s5(0, "rr");
    Student s6(3, "yy");
    Student s7(7, "uu");
    Student s8(1, "pp");
    Student s9(2, "mm");

    set<Student,greater<Student>> s;

    s.insert(s1); 
    s.insert(s2);
    s.insert(s3);
    s.insert(s4);
    s.insert(s5);
    s.insert(s6);
    s.insert(s7);
    s.insert(s8);
    s.insert(s9);

    for(set<Student>::iterator it = s.begin(); it != s.end(); it++)
    {
    
    
        it->show();
    }
    
    cout<<"set集合的大小 = "<<s.size()<<endl;  //自动排序,且键值对唯一

    cout<<"set的删除"<<endl;
    s.erase(s.begin());
    for(set<Student>::iterator it = s.begin(); it != s.end(); it++)
    {
    
    
        it->show();
    }

    cout<<"set的区间删除"<<endl;
    s.erase(--(s.end()),s.end());
    for(set<Student>:: iterator it = s.begin(); it != s.end(); it++)
    {
    
       
        it->show();
    }

    cout<<"set删除具体元素"<<endl;
    s.erase(s1);
    for(set<Student>:: iterator it = s.begin(); it != s.end(); it++)
    {
    
       
        it->show();
    }

    cout<<"set的查找"<<endl;
    set<Student,greater<Student>>::iterator it = s.find(s5);
    if(it == s.end())
    {
    
    
        cout<<"对象不存在"<<endl;
    }
    else
    {
    
    
        it->show();
    }
    cout<<"set的统计"<<endl;
    cout<<s.count(s6)<<endl;


    cout<<"low_bound"<<endl;
    Student ss(7,"tt");
    it = s.lower_bound(ss);
    if(it == s.end())
    {
    
    
        cout<<"对象不存在"<<endl;
    }
    else
    {
    
    
        it->show();
    }

    cout<<"upper_bound"<<endl;
   
    it = s.upper_bound(ss);
    if(it == s.end())
    {
    
    
        cout<<"对象不存在"<<endl;
    }
    else
    {
    
    
        it->show();
    }


    //pair类型,模板类 有两个成员变量
    cout<<"equal_range"<<endl;
    pair<set<Student,greater<Student>>::iterator,set<Student,greater<Student>>::iterator> p;
    p = s.equal_range(ss);  //返回一对迭代器给pair
    p.first->show();  //p.first第一个类型(迭代器)
    p.second->show();  //p.second第二个类型(迭代器)
    return 0;
}

1.7 map
map容器是标准的关联式容器,一个map是一个键值对的序列,即(key,value),它提供了基于key的快速检索能力。
map中key值是唯一的,集合中元素按照一定的顺序排列,元素不允许指定位置插入。
map也是红黑树变体的平衡二叉树的数据结构,插入和删除比vector快。
map可以直接根据key值来找到对应的value,支持[]操作符,比如map[key] = value。
multimap与map区别:map 支持唯一的键值,而mutimap支持同一个键值出现多次。multimap不支持[]操作符。

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

int main(int argc, char const *argv[])
{
    
    
    map<int,string> m;   //学号,姓名

    m.insert(pair<int,string>(3,"aa"));  //通过pair对组(组合一组)插入
    m.insert(pair<int,string>(4,"bb"));

    m.insert(make_pair(5,"cc"));  //通过make_pair组合一组数据
    m.insert(make_pair(6,"dd"));

    m.insert(map<int,string>::value_type(7,"ss"));   //通过map内部静态成员函数插入
    m.insert(map<int,string>::value_type(8,"pp"));

    m[2] = "ii";  //m重载[]运算符
    m[9] = "rr";

    for(map<int,string>::iterator it = m.begin(); it != m.end(); it++)
    {
    
    
        //it指向的是map的一个结点,一个节点就是一个pair对象
        cout<<"学号:"<<it->first<<"  姓名:"<<it->second<<endl;
    }
//插入方式区别:前三种方式,如果数据存在,返回错误,第四种方法,如果数据存在,将其覆盖。

    pair<map<int,string>::iterator,bool> p = m.insert(make_pair(5,"jj"));
    if(p.second == false)
    {
    
    
        cout<<"插入失败"<<endl;
        cout<<"学号:"<<p.first->first<<" 姓名:"<<p.first->second<<endl;
        cout<<"---------------"<<endl;
    }
    else
    {
    
    
        cout<<"插入成功"<<endl;
    }

    m[3] = "ww";
    for(map<int,string>::iterator it = m.begin(); it != m.end(); it++)
    {
    
    
        cout<<"学号:"<<it->first<<" 姓名:"<<it->second<<endl;
    }

    cout<<"删除区间"<<endl;
    m.erase(--(m.end()),m.end());
    for(map<int,string>::iterator it = m.begin(); it != m.end(); it++)
    {
    
    
        cout<<"学号:"<<it->first<<" 姓名:"<<it->second<<endl;
    }

    cout<<"删除具体元素"<<endl;
    m.erase(4);
    for(map<int,string>::iterator it = m.begin(); it != m.end(); it++)
    {
    
    
        cout<<"学号:"<<it->first<<" 姓名:"<<it->second<<endl;
    }
    return 0;
}

1.8 multimap
1个key可以对应多个value
案例 公司组织架构
销售部:3名,技术部:1名,财务部:4名
人员信息:姓名,年龄,电话,工资等
通过multimap进行信息的插入,保存,显示,分部门显示员工信息

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


class Employee
{
    
    
    private:
        int id;
        string name;
    public:
        Employee(int i, string n)
        {
    
    
            id = i;
            name = n;
        }
        void show()
        {
    
    
            cout<<"工号:"<<id<<"姓名:"<<name<<endl;
        }
};

int main(int argc, char const *argv[])
{
    
    
    Employee e1(1,"aa");
    Employee e2(2,"bb");
    Employee e3(3,"cc");
    Employee e4(4,"dd");
    Employee e5(5,"ee");
    Employee e6(6,"ff");
    Employee e7(7,"gg");
    Employee e8(8,"jj");

    multimap<string,Employee> m;
    
    //销售部
    m.insert(make_pair("sale",e1));
    m.insert(make_pair("sale",e2));
    m.insert(make_pair("sale",e3));

    //技术部
    m.insert(make_pair("Researcher",e4));

    //财务部
    m.insert(make_pair("Finance",e5));
    m.insert(make_pair("Finance",e6));
    m.insert(make_pair("Finance",e7));
    m.insert(make_pair("Finance",e8));

    cout<<m.count("Finance")<<endl;

    for (multimap<string,Employee>::iterator it = m.begin(); it != m.end();it++)
    {
    
    
        cout<<"部门:"<<it->first<<endl;
        it->second.show();
    }
    
    return 0;
}

在这里插入图片描述
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_43296982/article/details/124060463