美文网首页
C++常用容器复习

C++常用容器复习

作者: 盼旺 | 来源:发表于2019-08-23 15:58 被阅读0次

cin>>a cout<<a<<endl;

1.首先C++引入库的通用写法

#include <bits/stdc++.h>
using namespace std;
int main(){
    return 0;
}

相当于:

#include <iostream>
#include <cstdio>
#include <fstream>
#include <algorithm>
#include <cmath>
#include <deque>
#include <vector>
#include <queue>
#include <string>
#include <cstring>
#include <map>
#include <stack>
#include <set>

2.结构体

C++的结构体可以包含函数,这样,C++的结构体也具有类的功能,与class不同的是,结构体包含的函数默认为public,而不是private。

struct tag 
{
    member-list
}variable-list;
注:struct为结构体关键字;
   tag为结构体的标志;
   member-list为结构体成员变量及成员函数列表,其必须列出其所有成员;
   variable-list为此结构体声明的变量;

//带有指针般的结构体
struct dong{
    string name;
    int m;
    int v;
    dong *next;
};
dong a={"A",2,6,NULL};

//实现定一个ff[1500]的结构体数组
struct qwe
{
    int p,q,v;
}ff[1500];

//带有函数的结构体
struct SAMPLE
{
     int x;
     int y;
     int add() {return x+y;}
 }s1;

注意结构体分配空间的特殊性哦

3.声明函数

int GCD(int a,int b)
{
    if(b==0)
    return a;
    else
    return GCD(b,a%b);
}

4.构造函数的初始化列表

#include <iostream>
using namespace std;
class Student{
private:
    char *m_name;
    int m_age;
    float m_score;
public:
    Student(char *name, int age, float score);
    void show();
};
//采用初始化列表
Student::Student(char *name, int age, float score): m_name(name), m_age(age), m_score(score){
    //TODO:
}
void Student::show(){
    cout<<m_name<<"的年龄是"<<m_age<<",成绩是"<<m_score<<endl;
}
int main(){
    Student stu("小明", 15, 92.5f);
    stu.show();
    Student *pstu = new Student("李华", 16, 96);
    pstu -> show();
    return 0;
}
/*
小明的年龄是15,成绩是92.5
李华的年龄是16,成绩是96
*/

如本例所示,定义构造函数时并没有在函数体中对成员变量一一赋值,其函数体为空(当然也可以有其他语句),而是在函数首部与函数体之间添加了一个冒号:,后面紧跟m_name(name), m_age(age), m_score(score)语句,这个语句的意思相当于函数体内部的m_name = name; m_age = age; m_score = score;语句,也是赋值的意思。
使用构造函数初始化列表并没有效率上的优势,仅仅是书写方便,尤其是成员变量较多时,这种写法非常简单明了。
初始化列表可以用于全部成员变量,也可以只用于部分成员变量。

前面警示一下自己,下面复习STL中的容器

序列容器

①vector

vector是一个封装动态大小数组的序列容器

#include <bits/stdc++.h>
/*
1.需要引入 #include <vector>
2、Vector作为函数的参数或者返回值时,需要注意它的写法:
   double Distance(vector<int>&a, vector<int>&b) 其中的“&”绝对不能少!!!
   
(1)使用迭代器访问元素.
vector<int>::iterator it;
for(it=vec.begin();it!=vec.end();it++)
    cout<<*it<<endl;

(2)插入元素:    vec.insert(vec.begin()+i,a);在第i+1个元素前面插入a;
(3)删除元素:    vec.erase(vec.begin()+2);删除第3个元素
vec.erase(vec.begin()+i,vec.end()+j);删除区间[i,j-1];区间从0开始

(4) 使用reverse将元素翻转:需要头文件#include<algorithm>
reverse(vec.begin(),vec.end());将元素翻转,即逆序排列!

 vector <vector <int>     >   array2(3); 
          array2[1][2]=9; 
    保证你的程序会segement   failed,原因就是你没有指定向量的大小。
用push_back函数可以解决问题:array2[1].push_back(9);但是好象不太爽。就不能用operator[]吗?答案是肯定的。不过要多加几个步骤,
如下: 
            for(int   i=0;i <3;i++) 
                  array2[i].resize(3); 
    这样,你就定义了一个3X3的数组了(另一个3在   申明时定义的)。而且你可以随时改变它的大小。 
   */
using namespace std;
vector<int>test;//建立一个vector一维int数组 
vector<int>test2(10,7);//建立一个vector1维初始大小10,每个元素为7的int数组 
int main()
{
    vector<vector<int> > p(10);//这个10 不能少 
    for(int i=0;i<9;i++)//这个也不能少 
    p[i].resize(9);//resize 定义每一行的大小
    vector<int> pp(10,8);//1维 
    cout<<pp[1]<<endl;//8
    cout<<p[1][1]<<endl;// 输出0 没有p[i].resize(9);这个会报错
    vector<int> mp[10];//这样可以当2维 
//      for(int i=0;i<9;i++) 
//  mp[i].resize(9);
    mp[1].push_back(10);//经常这么用的 
    cout<<mp[1].size()<<endl; //1
    cout<<mp[1][0]<<endl;//10
}

②list

list是双向链表结构,它的数据由若干个节点构成,每一个节点都包括一个信息块(即实际存储的数据)、一个前驱指针和一个后驱指针。

list 的特点:

(1) 不使用连续的内存空间这样可以随意地进行动态操作;
(2) 可以在内部任何位置快速地插入或删除,当然也可以在两端进行push 和pop 。
(3) 不能进行内部的随机访问,即不支持[ ] 操作符和vector.at() ;
(4) 相对于verctor 占用更多的内存。
#include <bits/stdc++.h>
using namespace std;
int comp(int a){
    if(a==8)
    return 1;
    else
    return 0;
}
int main(){
    list<int> c0;//空链表
    list<int> c1(5);//含5个默认值是0的链表
    list<int> c2(5,2);//含5个默认值是2的链表
    list<int> c3(c2);//建一个c2的copy链表
    list<int> c4(c1.begin(),c1.end());//含c1一个区域元素的链表
    list<int>::iterator it;
    //在尾部插入
    c0.push_back(5); 
    c0.push_back(4);
    c0.push_back(7);
    c0.push_back(0);
    c0.push_back(8);
    //插入insert() 函数的第一个参数是用来指定插入位置的迭代器,第二个参数是被插入元素的个数
    it=c0.begin();//不能写成 c0.begin()+1 
    it++;
    c0.insert(it,3);
    //返回第一个
    cout<<c0.front()<<endl;
    //返回最后一个
    cout<<c0.back()<<endl;
    //list实际元素的个数 
    cout<<c0.size()<<endl;
    //删除第一个元素 注意删除之后it指代的元素 
    it=c0.begin(); 
    c0.erase(it);
    //所有容器做erase操作时都有可能使迭代器失效。改正的原理是使当前迭代器失效时能指向下一个位置
    cout<<*it<<endl; //输出删除的那个5
    //遍历
    for(it=c0.begin();it!=c0.end();it++){
        cout<<*it<<" ";
    } 
    cout<<endl;
    //默认升序排列 
    c0.sort();
    //遍历
    for(it=c0.begin();it!=c0.end();it++){
        cout<<*it<<" ";
    } 
    cout<<endl; 
    //删除第一个元素
    c0.pop_front();
    //删除最后一个元素
    c0.pop_back(); 
    //删除链表中匹配的元素
    c0.remove(0);
    //删除满足条件的元素 参数为自定义的回调 
    c0.remove_if(comp); 
    //遍历
    for(it=c0.begin();it!=c0.end();it++){
        cout<<*it<<" ";
    } 
} 

关联容器

①set

set这种容器里面存放元素唯一的,不可能有俩个重复的在里面,而且插入的元素是按从小到大排列

#include <iostream>
#include <set> //set这种容器里面存放元素唯一的,不可能有俩个重复的在里面,而且插入的元素是按从小到大排列 
using namespace std;
int main()
{
    set<int> st;
    set<int>::iterator it; 
    st.insert(2);
    st.insert(1);
    st.insert(3);
    st.insert(8);
    printf("%d\n",st.size());
    bool isempty=st.empty();//是否为空 
    int has1=st.count(1);//1这个元素是否在set里面 has1 要不为1 要不为0
    int has2=st.count(9);
    printf("%d %d\n",has1,has2);
    st.erase(1);//撤出1 这个元素
    ////lower_bound()--返回指向大于(或等于)某值的第一个元素的迭代器
    cout<<*st.lower_bound(1)<<endl;//返回set第一个大于等于1的数
    cout<<*st.upper_bound(1)<<endl;//返回set第一个大于1的数
    //遍历 
    it=st.begin();
    for(it;it!=st.end();it++){
        cout<<*it<<" ";
    }
    //返回与特定键匹配的元素数
    cout<<endl<<st.count(2)<<endl; 
    //返回与特定键匹配的元素数位置 
    st.clear();       
 } 

②map

Map中的元素是自动按key升序排序,所以不能对map用sort函数

/*、map的说明  
  1   头文件 
  #include   <map> 
  2   定义 
  map<string,   int>   my_Map; 
  或者是typedef     map<string,   int>   MY_MAP; 
  MY_MAP   my_Map; */
#include <bits/stdc++.h>
using namespace std;
int main()
{
    map<string, int> mm;//Map中的元素是自动按key升序排序,所以不能对map用sort函数:
    //插入数据与输出 
    mm["a"]=1;
    mm["qwer"]=78;
    mm.insert(pair<string,int>("ppp",2));
    mm["asd"]=-7;
    mm["ppp"]=78;
    cout<<mm["a"]<<endl;
    map<string,int>::iterator it;
    it=mm.find("qwer");//find()函数返回一个迭代器指向键值为key的元素,如果没找到就返回指向map尾部的迭代器。  
    cout<<it->second;////first是Key, second是value;
    it=mm.find("ppp");
    cout<<endl<<it->first<<" "<<it->second;
    it=mm.find("112");
    if(it==mm.end())//因为没找到会返回最后一个 
    {
        cout<<endl<<"没有找到"; 
    }
    else
    mm.erase(it);//删除元素 
    cout<<endl<<mm.max_size();//返回可以容纳的最大元素
    cout<<endl<<mm.size()<<endl;
    cout<<mm.count("ppp");//返回元素出现的次数 但是不是相同的会删除吗? 所以返回值只能是1和0 可以来判断存不存在 
 } 

容器适配器

①stack

stack 模板类的定义在<stack>头文件中。
stack 模板类需要两个模板参数,一个是元素类型,一个容器类型,但只有元素类型是必要的,在不指定容器类型时,默认的容器类型为deque。
定义stack 对象的示例代码如下:
stack<int> s1;
stack<string> s2;
stack 的基本操作有:
s.push(x); //入栈
s.pop(); //出栈,注意,出栈操作只是删除栈顶元素,并不返回该元素。
s.top(); //访问栈顶,但不删除该元素
s.empty(); //判断栈空,当栈空时,返回true。
s.size(); //访问栈中的元素个数

②queue

queue 模板类的定义在<queue>头文件中。
与stack 模板类很相似,queue 模板类也需要两个模板参数,一个是元素类型,一个容器类型,元素类型是必要的,容器类型是可选的,默认为deque 类型。
定义queue 对象的示例代码如下:
queue<int> q1;
queue<double> q2;
queue 的基本操作有:
q.push(x); //入队,将x 接到队列的末端。
q.pop(); //出队,弹出队列的第一个元素,注意,并不会返回被弹出元素的值。
q.front(); //访问队首元素,即最早被压入队列的元素。
q.back(); //访问队尾元素,即最后被压入队列的元素。
q.empty(); //判断队列空,当队列空时,返回true。
q.size(); //访问队列中的元素个数

stack栈顶是top,queue队首是front;

③priority_queue(优先队列)

priority_queue 模板类的定义在<queue>头文件中。
优先队列与队列的差别在于优先队列不是按照入队的顺序出队,而是按照队列中元素的优先权顺序出队(默认为大者优先,也可以通过指定算子来指定自己的优先顺序)。
priority_queue 模板类有三个模板参数
第一个是元素类型
第二个容器类型
第三个是比较算子
其中后两个都可以省略,默认容器为vector,默认算子为less,即小的往前排,大的往后排(出队时为列尾的元素出队)。
定义priority_queue 对象的示例代码如下:
priority_queue<int> q1;
priority_queue< pair<int, int> > q2;// 注意在两个尖括号之间一定要留空格。
priority_queue<int, vector<int>, greater<int> > q3; // 定义小的先出队
priority_queue 的基本操作与queue 相同。
初学者在使用priority_queue 时,最困难的可能就是如何定义比较算子了。
如果是基本数据类型,或已定义了比较运算符的类,
可以直接用STL 的less 算子和greater算子——默认为使用less 算子,即小的往前排,大的先出队。
如果要定义自己的比较算子,方法有多种,这里其中的一种:重载比较运算符。
优先队列试图将两个元素x 和y 代入比较运算符(对less 算子,调用x<y,对greater 算子,调用x>y),
若结果为真,则x 排在y 前面,y 将先于x 出队,反之,则将y 排在x 前面,x 将先出队。

下面几种重载运算符方法:

1.重载为友元函数:

struct node
{
    int x;
    int y;
    //要求按y大的排序,y相同x小的排序
    friend bool operator <(const node &a,const node &b)  //对应less算子
    {
        if(a.y==b.y)
            return a.x>b.x;  //x大的排在前,则出队时x小的先出队
        else
            return a.y<b.y;  //y小的排在前,则出队时y大的先出队
    }
    friend bool operator >(const node &a,const node &b)  //对应greater算子
    {
        if(a.y==b.y)
            return a.x>b.x;
        else
            return a.y<b.y;
    }
}Node;

2.重载为外部函数


struct node
{
    int x;
    int y;
    //要求按y大的排序,y相同x小的排序
}Node;
 
bool operator <(const node &a,const node &b)  //对应less算子
{
    if(a.y==b.y)
        return a.x>b.x;  //x大的排在前,则出队时x小的先出队
    else
        return a.y<b.y;  //y小的排在前,则出队时y大的先出队
}
bool operator >(const node &a,const node &b)  //对应greater算子
{
    if(a.y==b.y)
        return a.x>b.x;
    else
        return a.y<b.y;
}

参考文章

相关文章

  • C++常用容器复习

    cin>>a cout<

  • C++常用容器

    C++ 有两类常用容器,分别是顺序容器和关联容器,顺序容器例如vector,list,queue,关联容器例如ma...

  • C++容器、类型转换、异常与文件流操作

    C++容器、类型转换、异常与文件流操作 [TOC] 容器 容器,就是用来存放东西的盒子。常用的数据结构包括:数组a...

  • C/C++容器、类型转换、异常与文件流操作

    C++容器、类型转换、异常与文件流操作 [TOC] 容器容器,就是用来存放东西的盒子。 常用的数据结构包括:数组a...

  • 2018-10-27

    常用的4种C++组件: 类(class),集合和容器(collection and container),类库(c...

  • C++常用容器原理

    1. map 与unordered_map map:内部实现是一个红黑树,按key有序的unordered_map...

  • C++STL整理

    C++ STL中最基本以及最常用的类或容器string、vector、set、list、map string 处理...

  • STL备忘录——list

    前言 list是c++中非常常用的容器。它与vector的作用非常类似,是一种队列结构的容器。它采取了链式储存的结...

  • [C++] STL 容器

    参考:[C++] STL 容器 (一) - 基本介紹[C++] STL 容器 (二) - Iterator 部分示例:

  • C++boolan part3_week1

    C++容器的介绍及使用 C++中的容器大致可以分为两个大类:顺序容器和关联容器。顺序容器中有包含有顺序容器适配器。...

网友评论

      本文标题:C++常用容器复习

      本文链接:https://www.haomeiwen.com/subject/tqqzsctx.html