C++ STL 容器

news2024/11/24 15:29:12

引言--多看案例

STL概念

STL(Standard Template Library, 标准模板库 ), 是惠普实验室开发的一系列软件的统
称。
STL 6 大组件
容器 :
作用 : 容纳存储数据
分类 :
序列式容器:
强调值的排序,每个元素均有固定的位置, 除非用删除或插入的操
作改变这个位置,
vector, deque/queue, list;
关联式容器 :
非线性,更准确的说是二叉树结构,各元素之间没有严格的物理上
的顺序关系 ;
在数据中选择一个关键字 key ,这个 key 对数据起到索引的作用,方
便查找。
如: set/multiset Map/multimap 容器
注意 : 容器可以嵌套容器
算法 :
作用 : 操作数据 , 如插入数据、删除数据、修改数据、排序等
分类 :
质变算法:是指运算过程中会更改区间内的元素的内容。例如拷贝,替
换,删除等等
非质变算法:是指运算过程中不会更改区间内的元素内容,例如查找、
计数、遍历、寻找极值等等
迭代器
作用 : 容器与算法之间的粘合剂
注意 : 每个容器都有自己的迭代器
分类 :
输入迭代器 提供对数据的只读访问 只读,支持 ++ == 、! =
输出迭代器 提供对数据的只写访问 只写,支持 ++
前向迭代器 提供读写操作,并能向前推进迭代器 读写,支持 ++
== 、! =
双向迭代器 提供读写操作,并能向前和向后操作 读写,支持 ++ --
随机访问迭代器 提供读写操作,并能以跳跃的方式访问容器的任意数
据,是功能最强的迭代器读写,支持 ++ -- [n] - n < <= > >=
仿函数
作用 : 为算法提供策略
适配器
作用 : 为算法提供更多的参数接口
空间配置器
作用 : 为容器和算法管理空间

 常用容器

string

作用

存储字符的容器(字符串)

构造函数

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

using namespace std;

void fun01()

{

    string str01;

    cout<<"str01"<<str01<<endl;

    // string str02("hello");

    string str02("时间里的空白");

    cout<<"str02="<<str02<<endl;

    string str03=str02;

    cout<<"str03="<<str03<<endl;

    string str04(3,'A');

    cout<<"str04="<<str04<<endl;

}

基本赋值操作

语法

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 string &s);// 把字符串 s 赋给当前字符串
string& assign(int n, char c);// n 个字符 c 赋给当前字符串
string& assign(const string &s, int start, int n);// s start 开始 n
字符赋值给字符串
示例1

void fun02()

{

    string str01;

    cout<<"str01"<<str01<<endl;

    str01="何必难为自己";

    cout<<"str01"<<str01<<endl;

    string str02;

    str02=str01;

    cout<<"str02="<<str02<<endl;

    string str03;

    str03='a';

    cout<<"str03="<<str03<<endl;

}

示例2

void fun03()

{

// string& assign(const char *s);//把字符串s赋给当前的字符串

// string& assign(const char *s, int n);//把字符串s的前n个字符赋给当前的字符串

// string& assign(const string &s);//把字符串s赋给当前字符串

// string& assign(int n, char c);//用n个字符c赋给当前字符串

// string& assign(const string &s, int start, int n);//将s从 start开始n个字符赋值给字符串

string str01 = "hello";

cout << "str01 = " << str01 << endl;

str01.assign("world123");

cout<<"str01="<<str01<<endl;

str01.assign("mylove159",5);//mylov

cout<<"str01="<<str01<<endl;

str01.assign(3,'h');

cout<<"str01="<<str01<<endl;

string str02;

str02.assign(str01,0,2);

cout << "str02 = " << str02 << endl;

string str03;

str03.assign(str02);

cout<<"str03:"<<str03<<endl;

}

 获取字符串长度

语法

int size();

int length();

注意:不包含\0

示例

void fun04()

{

    string str="hello";

    int size=str.size();

    cout<<"size="<<size<<endl;

    int len=str.length();

    cout<<"len="<<len<<endl;

}

存取字符操作

语法

 char& operator[](int n);//通过[]方式取字符,下标越界不会抛出异常

 char& at(int n);// 通过 at 方法获取字符 , 下标越界会抛出异常
 示例

void fun05()

{

    string str="hello";

    cout<<str[2]<<endl;

    cout<<str.at(1)<<endl;

}

拼接操作

string& operator+=(const string& str);// 重载 += 操作符
string& operator+=(const char* str);// 重载 += 操作符
string& operator+=(const char c);// 重载 += 操作符
string& append(const char *s);// 把字符串 s 连接到当前字符串结尾
string& append(const char *s, int n);// 把字符串 s 的前 n 个字符连接到当前字符
串结尾
string& append(const string &s);// operator+=() string& append(const string &s, int pos, int n);// 把字符串 s 中从 pos 开始的
n 个字符连接到当前字符串结尾
string& append(int n, char c);// 在当前字符串结尾添加 n 个字符 c
示例

 void fun06()

{

    string str01="Hi";

    str01+="C++";

    cout<<"str01="<<str01<<endl;

    string str02="STL";

    str01+=str02;

    cout<<"str01="<<str01<<endl;

    str01+='A';

    cout<<"str01="<<str01<<endl;

}

void fun07()

{

    // string& append(const char *s);

    //把字符串s连接到当前字符串结尾

    string str01;

    str01.append("hi");

    cout<<"str01="<<str01<<endl;

    str01.append("C++");

    cout<<"str01="<<str01<<endl;

    // string& append(const char *s, int n);

    //把字符串s的前n个字符连接到当前字符串结尾

    string str02;

    str02.append("ggbang",5);

    cout<<"str02="<<str02<<endl;

    // string& append(const string &s);

    //同operator+=()

    // string& append(const string &s, int pos, int n);

    //把字符串s中从pos开始的n个字符连接到当前字符串结尾

    string str03="1234567890";

    string str04;

    str04.append(str03,3,2);

    cout<<"str04="<<str04<<endl;

    // string& append(int n, char c);

    //在当前字符串结尾添加n个字符c

    str04.append(2,'p');

    cout<<"str04="<<str04<<endl;

 查找和替换

语法
int find(const string& str, int pos = 0) const; // 查找 str 第一次出现位置 ,
pos 开始查找
int find(const 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 rfind(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 c, 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 个字符
为字符串 s
注意 : 查找是不存在返回 -1
 示例

void fun08()

{

    string str="456love456";

    int i01=str.find('4');

    cout<<"i01="<<i01<<endl;

    int i02=str.rfind('4');

    cout<<"i02="<<i02<<endl;

    int i03=str.find("6l");

    cout<<"i03="<<i03<<endl;

    str.replace(3,3,"15587554");

    cout<<"str="<<str<<endl;

}

比较操作

/**
*compare 函数在 > 时返回 1 < 时返回 -1 == 时返回 0
* 比较区分大小写,比较时参考字典顺序,排越前面的越小。大写的 A 比小写的 a 小。
**/
int compare(const string &s) const;// 与字符串 s 比较
int compare(const char *s) const;// 与字符串 s 比较

 截取操作

语法
string substr(int pos = 0, int n = npos) const;// 返回由 pos 开始的 n 个字符
组成的字符串
示例

 void fun09()

{

    string str01="a.txt";

    string str03="baby.go";

    string str02=str01.substr(1,4);

    string str04=str03.substr(1,3);

    cout<<str02<<endl;

    cout<<str04<<endl;

}

插入与删除

语法
string& insert(int pos, const char* s); // 插入字符串
string& insert(int pos, const string& str); // 插入字符串
string& insert(int pos, int n, char c);// 在指定位置插入 n 个字符 c
string& erase(int pos, int n = npos);// 删除从 Pos 开始的 n 个字符
示例

 void fun10()

{

// string& insert(int pos, const char* s); //插入字符串

// string& insert(int pos, const string& str); //插入字符串

// string& insert(int pos, int n, char c);//在指定位置插入n个字符c

string str01 = "11";

//开始位置不要超出字符串下标范围

// str01.insert(1,"abc");

str01.insert(1,3,'A');

cout << "str01 = " << str01 << endl;

// string& erase(int pos, int n = npos);//删除从Pos开始的n个字符

str01.erase(1,3);

cou

 string与char* 转换

//string转char*

string str="itcast";

const char* cstr=str.c_str();

//char*转string

char* s="itcast";

string str(s);

示例

void fun11()

{

string str01 = "abc";

string str02("abc");

cout<<str02<<endl;

char* str03 = (char* )str01.c_str();

cout<<str03<<endl;

}

重要案例

//解析字符串

void fun13()

{

    string str="www.itcast.com.cn";

    vector<string> v;

    int start=0;

    int pos=-1;

    while (true)

    {

        //www.itcast.com.cn

        pos=str.find(".",start);

        if (pos==-1)

        {

            //将cn截取出来

            string tempStr=str.substr(start,str.size()-start);

            v.push_back(tempStr);

            start=pos+1;

            break;

        }

        string tempStr=str.substr(start,pos-start);

        v.push_back(tempStr);

        start=pos+1;

    }

        for (vector<string>::iterator it=v.begin();it!=v.end();it++)

        {

            cout<<*it<<endl;

        }

   

}

/*

写一个函数,函数内部将string字符串中所有的小写字母都变成大写字母

*/

void fun14()

{

    string str="abcDEF";

    for (int i = 0; i < str.size(); i++)

    {

        // str[i]=toupper(str[i]);//全部转大写

        str[i]=tolower(str[i]);//全部转小写

    }

    cout<<str<<endl;

   

}

Vector

概述

连续开辟 , 单向开口 , 随机访问迭代器 , 有容量 , 每次扩容是原来的 2
底层数据结构 : 数组

 与数组区别

vector 的结构类同于数组,数组是静态的,在定义时确定的数组的大小;
vector 是动态的,添加元素时如果空间不足时,则会自动扩容器( 2^n); 这被称为
vector 的未雨绸缪机制
整体来说, vector 比较灵活的,而且 vector 是类模板,可以存放任意类型的元素

 迭代器

 构造函数

语法
vector<T> v; // 采用模板实现类实现,默认构造函数
vector(v.begin(), v.end());// v[begin(), end()) 区间中的元素拷贝给本
身。
vector(n, elem);// 构造函数将 n elem 拷贝给本身。
vector(const vector &vec);// 拷贝构造函数
 示例

void fun01()

{

    vector<int> v01;

    v01.push_back(1);

    v01.push_back(5);

    v01.push_back(3);

    vector<int>::iterator it=v01.begin();//获取开始位置的迭代器

    while (it!=v01.end())//end():结束位置

    {

        cout<<*it<<endl;//*it获取当前迭代器指向的位置的值

        it++;//迭代器后移1位

    }

}

void fun02()

{

    vector<int> v01;

    v01.push_back(6);//尾部添加

    v01.push_back(5);

    v01.push_back(12);

    vector<int> v02(v01.begin()+1,v01.begin()+2);//包含开始位置,不包含结束位置(前闭后开)

    //vector<int>::iterator it=v02.begin();

    auto it=v02.begin();//c++11及以上版本,编译时需加-std=c++11

    while (it!=v02.end())

    {

        cout<<*it<<endl;

        it++;

    }

}

void fun03()

{

    vector<int> v(10,5);

    auto it=v.begin();

    while (it!=v.end())

    {

        cout<<*it<<endl;

        it++;

    }

}

 赋值操作

语法
assign(beg, end);// [beg, end) 区间中的数据拷贝赋值给本身。
assign(n, elem);// n elem 拷贝赋值给本身。
vector& operator=(const vector &vec);// 重载等号操作符
swap(vec);// vec 与本身的元素互换
 示例

void fun04()

{

    // assign(beg, end);//将[beg, end)区间中的数据拷贝赋值给本身。

    // assign(n, elem);//将 n 个 elem 拷贝赋值给本身。

    // vector& operator=(const vector &vec);//重载等号操作符

    // swap(vec);// 将 vec 与本身的元素互换

    vector<int> v01;

    v01.push_back(1);

    v01.push_back(6);

    v01.push_back(9);

    v01.push_back(1);

    v01.push_back(3);

    v01.push_back(4);

    vector<int> v02;

    // v02.assign(v01.begin(),v01.begin()+3);

    // v02.assign(5,3);

    // v02 = v01;

    v02.push_back(2);

    v02.push_back(4);

    v02.swap(v01);

    auto it=v02.begin();

    while (it!=v02.end())

    {

        cout<<*it<<endl;

        it++;

    }

    cout<<"-------------"<<endl;

    auto it01=v01.begin();

    while (it01!=v01.end())

    {

        cout<<*it01<<endl;

        it01++;

    }

}

 插入与删除

语法
push_back(ele); // 尾部插入元素 ele
insert(const_iterator pos, int count, T ele); // 迭代器指向位置 pos 插入
count 个元素 ele.
pop_back();// 删除最后一个元素
erase(const_iterator start, const_iterator end); // 删除迭代器从 start
end 之间的元素 , 删除 [start, end) 区间的所有元素
erase(const_iterator pos); // 删除迭代器指向的元素
clear(); // 删除容器中所有元素
示例

void fun05()

{

    vector<int> v;

    // push_back(ele); //尾部插入元素 ele

    v.push_back(1);

    v.push_back(3);

    v.push_back(6);

    v.push_back(7);

    v.push_back(9);

    // insert(const_iterator pos, int count, T ele); //迭代器指向位置 pos 插入count个元素ele.

    v.insert(v.begin(),4,0);

    // pop_back();//删除最后一个元素

    v.pop_back();

    // erase(const_iterator start, const_iterator end); //删除迭代器从 start到 end 之间的元素,删除[start, end)区间的所有元素

    v.erase(v.begin()+1,v.begin()+3);

    // erase(const_iterator pos); //删除迭代器指向的元素

    // v.clear();

    // clear(); //删除容器中所有元素

    auto it=v.begin();

    while (it!=v.end())

    {

        cout<<*it<<endl;

        it++;

    }

}

 取值操作

语法
at(int idx); // 返回索引 idx 所指的数据,如果 idx 越界,抛出 out_of_range
异常。
operator[](int idx); // 返回索引 idx 所指的数据,越界时 , 不会直接报错
front(); // 返回容器中第一个数据元素
back(); // 返回容器中最后一个数据元素
 示例

void fun06()

{

    vector<int> v;

    v.push_back(1);

    v.push_back(12);

    v.push_back(7);

    v.push_back(6);

    v.push_back(2);

    // at(int idx); //返回索引 idx 所指的数据,如果 idx 越界,抛出 out_of_range异常。

    cout<<"v.at(3)="<<v.at(3)<<endl;

    // operator[](int idx); //返回索引 idx 所指的数据,越界时,不会直接报错

    cout<<"v[2]="<<v[100]<<endl;

    // front(); //返回容器中第一个数据元素

    cout<<v.front()<<endl;

    // back(); //返回容器中最后一个数据元素

    cout<<v.back()<<endl;

}

 大小相关

语法
int size(); // 返回容器中元素的个数
bool empty(); // 判断容器是否为空, 返回 bool 值( 0 1
void resize(int num); // 重新指定容器的长度为 num ,若容器变长,则以默认值填
充新位置。如果容器变短,则末尾超出容器长度的元素被删除。
void resize(int num, elem); // 重新指定容器的长度为 num ,若容器变长,则以
elem 值填充新位置。如果容器变短,则末尾超出容器长度的元素被删除。
int capacity(); // 容器的容量
void reserve(int len); // 容器预留 len 个元素长度
 示例

void fun07()

{

    vector<int> v;

    v.push_back(1);

    v.push_back(9);

    v.push_back(6);

    v.push_back(2);

    v.push_back(7);

    // cout<<v.size()<<endl;

    // int size(); // 返回容器中元素的个数

    cout<<v.empty()<<endl;

    // bool empty(); //判断容器是否为空, 返回bool值(0, 1)

    void resize(int num);

    // void resize(int num); //重新指定容器的长度为 num,若容器变长,则以默认值填充新位置。如果容器变短,则末尾超出容器长度的元素被删除。

    v.resize(2);

    // void resize(int num, elem); //重新指定容器的长度为 num,若容器变长,则以elem 值填充新位置。如果容器变短,则末尾超出容器长度的元素被删除。

    v.resize(10,10);

    // int capacity(); //容器的容量

    cout<<v.capacity()<<endl;

    // void reserve(int len); //容器预留 len 个元素长度

    v.reserve(10);

    cout<<v.capacity()<<endl;

    auto it = v.begin();

    while(it != v.end())

    {

    cout << *it << endl;

    it++;

    }

}

void fun08()

{

    vector<int> v;

    v.push_back(1);

    v.push_back(3);

    v.push_back(5);

    v.push_back(7);

    v.push_back(9);

    cout << "v的大小 = " << v.size() << endl;

    cout << "v的容量 = " << v.capacity() << endl;

    vector<int>(v).swap(v);

    cout << "v的大小 = " << v.size() << endl;

    cout << "v的容量 = " << v.capacity() << endl;

}

 存储自定义类型

示例

void fun09()

{

    vector<Per> ps;

    ps.push_back(Per("张三"));

    ps.push_back(Per("李四"));

    ps.push_back(Per("王五"));

    ps.push_back(Per("赵六"));

    for (auto it=ps.begin();it!=ps.end();it++)

    {

        cout<<(*it).name<<endl;

    }

}

 容器嵌套

void fun10()

{

    vector<int> v1;

    v1.push_back(10);

    v1.push_back(20);

    v1.push_back(30);

    v1.push_back(40);

    v1.push_back(50);

    v1.push_back(60);

    vector<int> v2;

    v2.push_back(100);

    v2.push_back(200);

    v2.push_back(300);

    v2.push_back(400);

    v2.push_back(500);

    vector<int> v3;

    v3.push_back(1000);

    v3.push_back(2000);

    v3.push_back(3000);

    v3.push_back(4000);

    v3.push_back(5000);

    vector<vector<int>> v;

    v.push_back(v1);

    v.push_back(v2);

    v.push_back(v3);

    vector<vector<int>>::iterator it=v.begin();

    for (; it!=v.end();it++)

    {

        //*it==vector<int>

        vector<int>::iterator mit=(*it).begin();

        for (;mit!=(*it).end();mit++)

        {

            //*mit==int

            cout<<*mit<<"";

        }

        cout<<endl;

    }

}

重要案例

void fun11()

{

    vector<int> v;

    v.push_back(10);

    v.push_back(20);

    v.push_back(30);

    v.push_back(40);

    v.push_back(50);

    v.push_back(60);

    //逆序遍历

    for (vector<int>::reverse_iterator it=v.rbegin();it!=v.rend();it++)

    {

       cout<<*it<<endl;

    }

    //vector的迭代器是随机访问迭代器,支持跳跃访问

    vector<int>::iterator itBegin=v.begin();

    itBegin=itBegin+3;

    cout<<*itBegin<<endl;

}

 deque

概述

deque 则是一种双向开口的连续线性空间。所谓的双向开口,意思是可以在头尾两端分
别做元素的插入和删除操作
数据结构 : 数组

与vector的区别

 一在于 deque 允许使用常数项时间对头端进行元素的插入和删除操作。

二在于 deque 没有容量的概念,因为它是动态的以分段连续空间组合而成,随时可以
增加一段新的空间并链接起来

 api

// 构造函数
deque<T> deqT;// 默认构造形式
deque(beg, end);// 构造函数将 [beg, end) 区间中的元素拷贝给本身。
deque(n, elem);// 构造函数将 n elem 拷贝给本身。
deque(const deque &deq);// 拷贝构造函数
// 赋值操作
assign(beg, end);// [beg, end) 区间中的数据拷贝赋值给本身。
assign(n, elem);// n elem 拷贝赋值给本身。
deque& operator=(const deque &deq); // 重载等号操作符
swap(deq);// deq 与本身的元素互换
// 大小操作
deque.size();// 返回容器中元素的个数
deque.empty();// 判断容器是否为空
deque.resize(num);// 重新指定容器的长度为 num, 若容器变长,则以默认值填充新
位置。如果容器变短,则末尾超出容器长度的元素被删除。
deque.resize(num, elem); // 重新指定容器的长度为 num, 若容器变长,则以 elem
值填充新位置 , 如果容器变短,则末尾超出容器长度的元素被删除。
// 双端插入和删除操作
push_back(elem);// 在容器尾部添加一个数据
push_front(elem);// 在容器头部插入一个数据
pop_back();// 删除容器最后一个数据
pop_front();// 删除容器第一个数据
// 数据存取
at(idx);// 返回索引 idx 所指的数据,如果 idx 越界,抛出 out_of_range
operator[];// 返回索引 idx 所指的数据,如果 idx 越界,不抛出异常,直接出
错。
front();// 返回第一个数据。
back();// 返回最后一个数据
// 插入操作
insert(pos,elem);// pos 位置插入一个 elem 元素的拷贝,返回新数据的位置。
insert(pos,n,elem);// pos 位置插入 n elem 数据,无返回值。
insert(pos,beg,end);// pos 位置插入 [beg,end) 区间的数据,无返回值。
// 删除操作
clear();// 移除容器的所有数据
erase(beg,end);// 删除 [beg,end) 区间的数据,返回下一个数据的位置。
erase(pos);// 删除 pos 位置的数据,返回下一个数据的位置。

stack

概念

(先进后出,又名水桶),单向开口,没有迭代器

 

 api

构造函数
stack<T> stkT;//stack 采用模板类实现, stack 对象的默认构造形式:
stack(const stack &stk);// 拷贝构造函数
赋值操作
stack& operator=(const stack &stk);// 重载等号操作符
数据存取操作
push(elem);// 向栈顶添加元素
pop();// 从栈顶移除第一个元素
top();// 返回栈顶元素
大小操作
empty();// 判断堆栈是否为空
size();// 返回堆栈的大小

 示例

void fun01()

{

    stack<int> s;

    //入栈

    s.push(10);

    s.push(20);

    s.push(30);

    s.push(40);

    while (!s.empty())

    {

        //访问栈顶元素

        cout<<s.top()<<endl;

        //出栈

        s.pop();

    }

    cout<<"size="<<s.size()<<endl;

}

 queue

概念

队列 ( 先进先出 ), 又名水管 , 双向开口 , 没有迭代器
队头 : 出数据
队尾 : 入数据

api

构造函数
queue<T> queT;//queue 采用模板类实现, queue 对象的默认构造形式:
queue(const queue &que);// 拷贝构造函数
存取、插入和删除操作
push(elem);// 往队尾添加元素
pop();// 从队头移除第一个元素
back();// 返回最后一个元素
front();// 返回第一个元素
赋值操作
queue& operator=(const queue &que);// 重载等号操作符
大小操作
empty();// 判断队列是否为空
size();// 返回队列的大小

示例

 #include<iostream>

#include<queue>

#include<string>

using namespace std;

class Person

{

public:

    Person(string name,int age)

    {

        this->m_Name=name;

        this->m_Age=age;

    }

    string m_Name;

    int m_Age;

};

void fun01()

{

    queue<Person> Q;//队列容器

    Person p1("张三",18);

    Person p2("李四",10);

    Person p3("王五",12);

    Person p4("赵六",28);

    Person p5("二狗",30);

    //入队

    Q.push(p1);

    Q.push(p2);

    Q.push(p3);

    Q.push(p4);

    Q.push(p5);

    cout<<"size="<<Q.size()<<endl;

    while (!Q.empty())

    {

        cout<<"队头元素--姓名"<<Q.front().m_Name<<"年龄:"<<Q.front().m_Age<<endl;

        cout<<"队尾元素--姓名"<<Q.back().m_Name<<"年龄:"<<Q.back().m_Age<<endl;

        //出队

        Q.pop();

    }

    cout<<"size="<<Q.size()<<endl;

}

int main(int argc, char const *argv[])

{

    fun01();

    return 0;

}

list 

概念

基于双向链表的 , 离散存储的 , 双向迭代器 , 元素可重复
数据结构 : 链表
双向迭代器 : 可以 ++,--, 但是不能 +,-,不支持随机访问

 

api 

构造函数
list<T> lstT;//list 采用采用模板类实现 , 对象的默认构造形式:
list(beg,end);// 构造函数将 [beg, end) 区间中的元素拷贝给本身。
list(n,elem);// 构造函数将 n elem 拷贝给本身。
list(const list &lst);// 拷贝构造函数。
数据元素插入和删除操作
push_back(elem);// 在容器尾部加入一个元素
pop_back();// 删除容器中最后一个元素
push_front(elem);// 在容器开头插入一个元素
pop_front();// 从容器开头移除第一个元素
insert(pos,elem);// pos 位置插 elem 元素的拷贝,返回新数据的位置。
insert(pos,n,elem);// pos 位置插入 n elem 数据,无返回值。
insert(pos,beg,end);// pos 位置插入 [beg,end) 区间的数据,无返回值。
clear();// 移除容器的所有数据
erase(beg,end);// 删除 [beg,end) 区间的数据,返回下一个数据的位置。
erase(pos);// 删除 pos 位置的数据,返回下一个数据的位置。
remove(elem);// 删除容器中所有与 elem 值匹配的元素。
大小操作
size();// 返回容器中元素的个数
empty();// 判断容器是否为空
resize(num);// 重新指定容器的长度为 num ,若容器变长,则以默认值填充新位
置。如果容器变短,则末尾超出容器长度的元素被删除。
resize(num, elem);// 重新指定容器的长度为 num, 若容器变长,则以 elem
填充新位置。如果容器变短,则末尾超出容器长度的元素被删除。
赋值操作
assign(beg, end);// [beg, end) 区间中的数据拷贝赋值给本身。
assign(n, elem);// n elem 拷贝赋值给本身。
list& operator=(const list &lst);// 重载等号操作符
swap(lst);// lst 与本身的元素互换。
数据的存取
front();// 返回第一个元素。
back();// 返回最后一个元素。
反转排序
reverse();// 反转链表,比如 lst 包含 1,3,5 元素,运行此方法后, lst 就包
5,3,1 元素。
sort(); //list 排序

示例

//遍历链表

void printList(list<int> & L)

{

    for (list<int>::iterator it=L.begin();it!=L.end();it++)

    {

        cout<<*it<<endl;

    }

}

void fun01()

{

    list<int> nums;

    nums.push_back(1);

    nums.push_back(5);

    nums.push_back(3);

    nums.push_back(7);

    nums.reverse();

    printList(nums);

}

void fun02()

{

    list<int> nums;

    nums.push_back(1);

    nums.push_back(5);

    nums.push_back(3);

    nums.push_back(7);

    nums.sort();

    printList(nums);

}

void fun03()

{

    list<int> nums;

    nums.push_back(1);

    nums.push_back(5);

    nums.push_back(3);

    nums.push_back(7);

    nums.sort();

    nums.reverse();

    printList(nums);

}

void fun04()

{

    list<int> nums;

    nums.push_back(1);

    nums.push_back(5);

    nums.push_back(3);

    nums.push_back(7);

    printList(nums);

    cout<<"-------------"<<endl;

    nums.push_front(22);

    nums.push_front(33);

    nums.push_front(66);

    printList(nums);

    cout<<"-------------"<<endl;

    nums.pop_back();//尾删

    nums.pop_front();//头删

    printList(nums);

    cout<<"-------------"<<endl;

    //插入

    nums.insert(nums.begin(),8888);

    printList(nums);

    cout<<"-------------"<<endl;

    nums.erase(nums.begin());

    printList(nums);

    cout<<"-------------"<<endl;

    //remove 直接删除数组内该元素,将一样的也一起删除

    nums.push_back(22);

    nums.push_back(22);

    nums.remove(22);

    nums.remove(33);

    printList(nums);

}

//遍历链表

void printList(list<int> & L)

{

    for (list<int>::iterator it=L.begin();it!=L.end();it++)

    {

        cout<<*it<<endl;

    }

}

bool myCompare(int v1,int v2)

{

    return v1>v2;

}

void fun05()

{

    list<int> L;

    L.push_back(10);

    L.push_back(20);

    L.push_back(30);

    L.push_front(100);

    L.push_front(200);

    L.push_front(300);

    //反转

    L.reverse();

    printList(L);

    cout<<"----------------"<<endl;

    //排序 如果容器的迭代器支持随机访问,可以使用系统提供的标志算法

    //不支持随机访问的迭代器容器,内部会提供对应的算法接口

    //sort(L.begin(),L.end());

    L.sort(myCompare);

    printList(L);

}

//遍历链表

void printList(list<int> & L)

{

    for (list<int>::iterator it=L.begin();it!=L.end();it++)

    {

        cout<<*it<<endl;

    }

}

class Person

{

public:

    Person(string name,int age,int height)

    {

        this->m_Name=name;

        this->m_Age=age;

        this->m_Height=height;

    }

    bool operator==(const Person & p)

    {

        if (this->m_Name==p.m_Name&&this->m_Age==p.m_Age&&this->m_Height==p.m_Height)

        {

            return true;

        }

        return false;

    }

    string m_Name;

    int m_Age;

    int m_Height;

};

bool myComparePerson(Person &p1,Person &p2)

{

    if (p1.m_Age==p2.m_Age)

    {

        return p1.m_Height<p2.m_Height;

    }

   

    return p1.m_Age>p2.m_Age;

}

void fun06()

{

    list<Person> L;

    Person p1("王尼玛",17,178);

    Person p2("法外狂徒",27,153);

    Person p3("李大奔",22,168);

    Person p4("沙巴特",44,172);

    Person p5("杀马特",5,145);

    Person p6("狗哥",36,197);

    Person p7("刘备",26,170);

    Person p8("关羽",26,217);

    Person p9("张飞",26,194);

   

    L.push_back(p1);

    L.push_back(p2);

    L.push_back(p3);

    L.push_back(p4);

    L.push_back(p5);

    L.push_back(p6);

    L.push_back(p7);

    L.push_back(p8);

    L.push_back(p9);

    //按照年龄进行降序   从大到小,如果年龄相等,按照身高进行升序

    //对于自定义数据类型,必须要指定排序规则

    L.sort(myComparePerson);

    for (list<Person>::iterator it=L.begin();it!=L.end();it++)

    {

        cout<<"姓名:"<<(*it).m_Name<<"  年龄:"<<it->m_Age<<"  身高:"<<it->m_Height<<endl;

    }

    //删除杀马特

    L.remove(p5);

    cout<<"删除杀马特后"<<endl;

    for (list<Person>::iterator it=L.begin();it!=L.end();it++)

    {

        cout<<"姓名:"<<(*it).m_Name<<"  年龄:"<<it->m_Age<<"  身高:"<<it->m_Height<<endl;

    }

}

 注意:如果利用remove删除自定义数据类型,需要重载==

set/multiset

set特点

Set 的特性是所有元素都会根据元素的键值自动被排序。
set 容器的键值和实值 是同一个值。
Set 不允许两个元素 有相同的键值。
Set 容器的迭代器 是只读迭代器。 插入数据后 不允许修改 set 的键值。
数据结构 : 红黑树
注意 :
如果存入的值大于原有的值 , 此时 x > y 为真 , 存入的值在原有值左边
如果存储的值小于原有的值 , 此时 x > y 为假 , 交换在比较
如果交换后 , 存储的值为 y, 原有值的为 x, 此时 x > y 为真 , 存入的值不应该在原有
值左边
如果交换后 , 存储的值为 y, 原有值的为 x, 此时 x > y 为假 , 此时证明不符合其存储
原则

 multiset特点

multiset 特性及用法和 set 完全相同,唯一的差别在于它允许键值重复。
数据结构 : 红黑树

api

 构造函数

set<T> st;//set 默认构造函数:
mulitset<T> mst; //multiset 默认构造函数 :
set(const set &st);// 拷贝构造函数
赋值操作
set& operator=(const set &st);// 重载等号操作符
swap(st);// 交换两个集合容器
大小操作
size();// 返回容器中元素的数目
empty();// 判断容器是否为空
插入和删除操作
insert(elem);// 在容器中插入元素。 clear();// 清除所有元素
erase(pos);// 删除 pos 迭代器所指的元素,返回下一个元素的迭代器。
erase(beg, end);// 删除区间 [beg,end) 的所有元素 ,返回下一个元素的迭代器。
erase(elem);// 删除容器中值为 elem 的元素。
查找操作
find(key);// 查找键 key 是否存在 , 若存在,返回该键的元素的迭代器;若不存在,
返回 set.end();
count(key);// 查找键 key 的元素个数
lower_bound(keyElem);// 下限返回第一个 key>=keyElem 元素的迭代器。
upper_bound(keyElem);// 上限返回第一个 key>keyElem 元素的迭代器。
equal_range(keyElem);// 返回容器中 key keyElem 相等的上下限的两个迭代
器。

示例

 void printSet(set<int>&s)

{

    for (set<int>::iterator it=s.begin();it!=s.end();it++)

    {

        cout<<*it<<endl;

    }

}

void fun01()

{

    set<int>s;

    s.insert(10);

    s.insert(30);

    s.insert(20);

    s.insert(40);

    s.insert(90);

    s.insert(60);

    printSet(s);

    if (s.empty())

    {

        cout<<"set容器为空"<<endl;

    }

    else

    {

        cout<<"set容器不为空 大小为:"<<s.size()<<endl;

    }

    s.erase(40);

    printSet(s);

}

void fun02()

{

    set<int>s;

    s.insert(10);

    s.insert(30);

    s.insert(20);

    s.insert(40);

    s.insert(90);

    s.insert(60);

    set<int>::iterator pos=s.find(30);

    if (pos!=s.end())

    {

        cout<<"找到了元素"<<*pos<<endl;

    }

    else

    {

        cout<<"没找到"<<endl;

    }

    //对于set而言,要么0 要么1

    int num=s.count(40);

    cout<<"key为40的个数为:"<<num<<endl;

    //lower_bound(keyElem);//返回第一个key>=keyElem元素的迭代器

    set<int>::iterator pos2=s.lower_bound(30);

    if (pos2!=s.end())

    {

        cout<<"lower_bound的值为:"<<*pos2<<endl;

    }

    else

    {

        cout<<"未找到"<<endl;

    }

    //upper_bound(keyElem);//返回第一个key>keyElem元素的迭代器

    pos2=s.upper_bound(30);

        if (pos2!=s.end())

    {

        cout<<"lower_bound的值为:"<<*pos2<<endl;

    }

    else

    {

        cout<<"未找到"<<endl;

    }

    //equal_range(keyElem);//返回容器中key与keyElem相等的上下限的两个迭代器

    pair<set<int>::iterator,set<int>::iterator>ret=s.equal_range(30);

    if (ret.first!=s.end())

    {

        cout<<"equal_range中的lower_bound的值为:"<<*ret.first<<endl;

    }

      if (ret.second!=s.end())

    {

        cout<<"equal_range中的upper_bound的值为:"<<*ret.second<<endl;

    }

   

}

map/multimap

map概述

 键值对的形式存储数据,一个键值对称为一个对组

这一对值可以具有不同的数据类型,两个值可以分别用 pair( 对组 ) 的两个公共的成员
变量 first( ) second( ) 访问。
不允许键重复

multimap概述

 允许键重复

api

map 构造函数

map<T1, T2> mapTT;//map 默认构造函数 :
T1: 键的数据类型 , 要有可比较性 , 基本数据类型都有可比性
T2: 值的数据类型
map(const map &mp);// 拷贝构造函数
map 赋值操作
map& operator=(const map &mp);// 重载等号操作符
swap(mp);// 交换两个集合容器
map 大小操作
size();// 返回容器中元素的数目
empty();// 判断容器是否为空
map 插入数据元素操作
map.insert(...); // 往容器插入元素,返回 pair<iterator,bool>
map 删除操作
clear();// 删除所有元素
erase(pos);// 删除 pos 迭代器所指的元素,返回下一个元素的迭代器。
erase(beg,end);// 删除区间 [beg,end) 的所有元素 ,返回下一个元素的迭代器。
erase(keyElem);// 删除容器中 key keyElem 的对组。
map 查找操作
find(key);// 查找键 key 是否存在 , 若存在,返回该键的元素的迭代器;若不存在,
返回 map.end();
count(keyElem);// 返回容器中 key keyElem 的对组个数。对 map 来说,要么
0 ,要么是 1 。对 multimap 来说,值可能大于 1
lower_bound(keyElem);// 返回第一个 key>=keyElem 元素的迭代器。
upper_bound(keyElem);// 返回第一个 key>keyElem 元素的迭代器。
equal_range(keyElem);// 返回容器中 key keyElem 相等的上下限的两个迭代
器。

示例

void fun01()

{

    map<int,int>m;

    //第一种插入方式

    m.insert(pair<int,int>(1,10));

    //第二种插入方式  推荐

    m.insert(make_pair(2,20));

    //第三种插入方式

    m.insert(map<int,int>::value_type(3,30));

    //第四种

    m[4]=40;

    for (map<int,int>::iterator it=m.begin();it!=m.end();it++)

    {

        cout<<"key="<<it->first<<"value="<<it->second<<endl;

    }

    cout<<"------------"<<endl;

    m.erase(3);//删除传入key的值

    for (map<int,int>::iterator it=m.begin();it!=m.end();it++)

    {

        cout<<"key="<<it->first<<"value="<<it->second<<endl;

    }

   

}

void fun02()

{

    map<int,int>m;

    //第一种插入方式

    m.insert(pair<int,int>(1,10));

    //第二种插入方式  推荐

    m.insert(make_pair(2,20));

    //第三种插入方式

    m.insert(map<int,int>::value_type(3,30));

    //第四种

    m[4]=40;

    map<int,int>::iterator ret=m.find(3);

    if (ret!=m.end())

    {

        cout<<"找到了key为"<<ret->first<<"value="<<ret->second<<endl;

    }

    else

    {

        cout<<"未找到"<<endl;

    }

    int num=m.count(4);

    cout<<"key为4的对组个数为:"<<num<<endl;

    //lower_bound(keyElem);//返回第一个key>=keyElem元素的迭代器

    map<int,int>::iterator pos=m.lower_bound(3);

    if (pos!=m.end())

    {

        cout<<"找到了lower_bound key:"<<pos->first<<"value="<<pos->second<<endl;

    }

    else

    {

        cout<<"未找到"<<endl;

    }

    //upper_bound(keyElem);//返回第一个key>keyElem元素的迭代器

    pos=m.upper_bound(3);

    if (pos!=m.end())

    {

        cout<<"找到了upper_boun key:"<<pos->first<<"value="<<pos->second<<endl;

    }

    else

    {

        cout<<"未找到"<<endl;

    }

    //equal_range(keyElem);//返回容器中key与keyElem相等的上下限的两个迭代器

    pair<map<int,int>::iterator,map<int,int>::iterator> ret2=m.equal_range(3);

    if (ret2.first!=m.end())

    {

        cout<<"找到了equal_range中的lower_bound的key="<<ret2.first->first<<"value="<<ret2.first->second<<endl;

    }

    else

    {

        cout<<"未找到"<<endl;

    }

    if (ret2.second!=m.end())

    {

        cout<<"找到了equal_range中的upper_boun的key="<<ret2.second->first<<"value="<<ret2.second->second<<endl;

    }

    else

    {

        cout<<"未找到"<<endl;

    }

   

}

class myCompareInt

{

public:

    bool operator()(int v1,int v2)

    {

        return v1>v2;

    }

};

void fun03()

{

    map<int,int,myCompareInt>m;

    //第一种插入方式

    m.insert(pair<int,int>(1,10));

    //第二种插入方式  推荐

    m.insert(make_pair(2,20));

    //第三种插入方式

    m.insert(map<int,int>::value_type(3,30));

    //第四种

    m[4]=40;

    for (map<int,int,myCompareInt>::iterator it=m.begin();it!=m.end();it++)

    {

        cout<<"key="<<it->first<<"value="<<it->second<<endl;

    }

   

}

总结

 vector 单端动态数组 随机访问迭代器 (重点)

比如软件历史操作记录的存储,我们经常要查看历史记录,比如上一次的记录,上上次
的记录,但却不会去删除记录,因为记录是事实的描述。
数据结构 : 数组
deque :双端动态数组 随机访问迭代器
deque 的使用场景:比如排队购票系统,对排队者的存储可以采用 deque ,支持头端
的快速移除,尾端的快速添加
stack 栈容器 没有迭代器 先进后出
queue 队列容器 没有迭代器 先进先出
list 链表容器 双向迭代器 ( 重点 )
比如公交车乘客的存储,随时可能有乘客下车,支持频繁的不确实位置元素的移除插入
数据结构 : 双链表
set 容器 只有键值 键值不能重复 自动排序 只读迭代器
比如对手机游戏的个人得分记录的存储,存储要求从高 分到低分的顺序排列。
数据结构 : 红黑树
map 容器: 键值 - 实值成对出现 键值不能重复 自动排序 只读迭代器 ( 重点 )
比如按 ID 号存储十万个用户,想要快速要通过 ID 查找对应的用户。
数据结构 : 红黑树

评委打分案例 

​​​​​​​#include<iostream>

#include<vector>

#include<string>

#include<deque>

#include<stdlib.h>

#include<algorithm>

#include<time.h>

using namespace std;

/*

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

1.创建5名选手,放到vector中

2.遍历vector容器,取出每一个选手,执行for循坏,可以把10个评分打分存到deque容器中

3.sort算法对deque容器中分数排序,pop_back pop_front去除最高和最低分

4.deque容器遍历一遍,累加分数,累加分数/d.size()

5.person.score=平均分

*/

class Player

{

public:

    Player(string name,int score)

    {

        this->m_Name=name;

        this->m_Score=score;

    }

    string m_Name;//姓名

    int m_Score;//平均分

};

void createPlayer(vector<Player>&v)  //必须用引用的方式接收

{

    string nameSeed="ABCDE";

    for(int i=0;i<5;i++)

    {

        string name="选手";

        name+=nameSeed[i];

        int score=0;

        Player player(name,score);

        v.push_back(player);

    }

}

void setScore(vector<Player>&v)

{

    for (vector<Player>::iterator it=v.begin();it!=v.end();it++)

    {

        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_back();//最高分

    d.pop_front();//最低分


 

    //总分

    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<Player> &v)

{

    for (vector<Player>::iterator it=v.begin();it!=v.end();it++)

    {

         cout<<"姓名:"<<(*it).m_Name<<" 平均分数:"<<(*it).m_Score<<endl;

    }

   

}

int main(int argc, char const *argv[])

{

    //设置随机数种子

    srand((unsigned int)time(NULL));

    //1.创建5名选手

    vector<Player> v;

    createPlayer(v);

    //2.打分

    setScore(v);


 

    //3.显示平均分

    showScore(v);

    // for (vector<Player>::iterator it=v.begin();it!=v.end();it++)

    // {

    //     cout<<"姓名:"<<(*it).m_Name<<" 分数:"<<(*it).m_Score<<endl;

    // }

   

    return 0;

}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2072298.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

深度学习与神经网络戴做讲解

深度学习指导&#xff0c;计算机视觉指导。检测&#xff0c;分割&#xff0c;视频处理&#xff0c;估计&#xff0c;人脸&#xff0c;目标跟踪&#xff0c;图像&视频检索/视频理解&#xff0c;医学影像&#xff0c;GAN/生成式/对抗式&#xff0c;图像生成/图像合成&#xf…

C++ 设计模式——迭代器模式

迭代器模式 C 设计模式——迭代器模式1. 主要组成成分2. 迭代器模式范例2.1 抽象迭代器2.2 抽象容器2.3 具体的迭代器2.4 具体的容器2.5 主函数示例 3. 迭代器 UML 图3.1 迭代器 UML 图解析 4. 迭代器模式的优点5. 迭代器模式的缺点6. 迭代器模式的适用场景7. 现代C中的迭代器总…

【kubernetes】相关pod的创建和命令

【书写方法】&#xff1a; 管理使用k8s集群时&#xff0c;创建资源的Yaml文件非常重要&#xff0c;如何快速手写呢&#xff1f; 根据命令提示书写&#xff1a; kubectl explain [资源名称]例如打算写pod资源文件时&#xff0c;可查看如下&#xff1a; # 查看pod下所有字段 …

20. elasticsearch进阶_数据可视化与日志管理

20. 数据可视化 本章概述一. `elasticsearch`实现数据统计1.1 创建用户信息索引1.1.1 控制台创建`aggs_user`索引1.1.2 `aggs_user`索引结构初始化1.1.3 `aggs_user`索引的`EO`对象1.1.4 用户类型枚举1.1.5 数据初始化1.2 内置统计聚合1.2.1 `terms`与`date_histogram``terms``…

RocketMQ指南(二)高级篇

高级篇 1. 高级功能 1.1 消息存储 分布式队列因为有高可靠性的要求&#xff0c;所以数据要进行持久化存储。 消息生成者发送消息MQ收到消息&#xff0c;将消息进行持久化&#xff0c;在存储中新增一条记录返回ACK给生产者MQ push 消息给对应的消费者&#xff0c;然后等待消…

一文学会Shell中case语句和函数

大家好呀&#xff01;今天简单聊一聊Shell中的case语句与函数。在多选择情况下使用case语句将非常方便&#xff0c;同时&#xff0c;函数的学习和使用对于学好一门编程语言也是非常重要的。 一、case语句 case语句为多选择语句。可以用case语句匹配一个值与一个模式&#xff0c…

g++,gcc

由一个错误引发对这个问题的关注 上面我对于cpp文件利用gcc进行编译时产生的错误&#xff0c;起初我以为时三方库安装版本问题&#xff0c;反复卸载重装&#xff0c;发现仍然没有解决。然后我把目光聚焦到gcc编译这&#xff0c;发现把gcc改成g&#xff0c;编译就通过了。 g和 …

回归分析系列14.2— 正则化回归

16 正则化回归 16.1 简介 正则化回归是一种在回归模型中引入约束的技术,目的是防止模型过拟合并提高其泛化能力。最常见的正则化方法有岭回归(L2正则化)和套索回归(L1正则化)。这些方法通过添加惩罚项来限制模型参数的大小,从而降低模型的复杂度。 16.2 岭回归(L2正则…

OpenStack命令行发放云主机

source keystonerc_admin 查看环境变量 创建租户&#xff08;项目&#xff09; openstack project create hds 创建用户 openstack user create hds --password 1 --project hds 追加角色 openstack role add_member --user hds --project hds 创建规格 openstack flavor cr…

警惕.mkp勒索病毒:如何有效预防.mkp勒索病毒攻击

导言&#xff1a; 在数字化时代&#xff0c;网络安全问题日益严峻&#xff0c;勒索病毒作为一种极具破坏性的恶意病毒&#xff0c;严重威胁着个人用户和企业机构的数据安全。其中&#xff0c;.mkp勒索病毒以其强大的加密能力和广泛的传播方式&#xff0c;成为近期备受关注的网…

Linux 命令重定向介绍

今天给伙伴们分享一下Linux 命令重定向&#xff0c;希望看了有所收获。 我是公众号「想吃西红柿」「云原生运维实战派」作者&#xff0c;对云原生运维感兴趣&#xff0c;也保持时刻学习&#xff0c;后续会分享工作中用到的运维技术&#xff0c;在运维的路上得到支持和共同进步&…

Linux磁盘实用指令

目录 磁盘实用指令 磁盘实用指令 显示opt目录下的文件和目录 。 筛选出第一个符号为-的。 wc指令统计数目。 将符号-改为d就可以统计目录数目。 添加一个大写的r就可以递归的显示子目录了。 再与之前同理筛选出文件即可。 包括子文件夹的话加个大写的r即可 。 没有是因为默认情…

第2章-07-客户端IP与UserAgent

🏆作者简介,黑夜开发者,CSDN领军人物,全栈领域优质创作者✌,CSDN博客专家,阿里云社区专家博主,2023年CSDN全站百大博主。 🏆数年电商行业从业经验,历任核心研发工程师,项目技术负责人。 🏆本文已收录于专栏:Web爬虫入门与实战精讲,后续完整更新内容如下。 文章…

WLAN基础概念与实验

目录 1.WLAN 1.1 WLAN 基本概念和用途 1.2 WLAN 的用途 2.实验基本信息 2.1 实验top 2.2 实验要求 3.实验配置 3.1 基础配置 3.1.1 Router 3.1.2 SW1 3.1.3 SW2 3.1.4 AC6605 3.2 上线配置&#xff08;AC6605&#xff09; 3.3无线的下发 3.3.1 配置用户认证方式…

论文翻译:Multi-step Jailbreaking Privacy Attacks on ChatGPT

Multi-step Jailbreaking Privacy Attacks on ChatGPT https://arxiv.org/pdf/2304.05197 多步骤越狱隐私攻击对ChatGPT的影响 文章目录 多步骤越狱隐私攻击对ChatGPT的影响摘要1 引言2 相关工作3 对ChatGPT的数据提取攻击3.1 数据收集3.2 攻击制定3.3 从ChatGPT中提取私人数据…

Day47 | 110.字符串接龙 105.有向图的完全可达性 106.岛屿的周长

110.字符串接龙 110. 字符串接龙 题目 题目描述 字典 strList 中从字符串 beginStr 和 endStr 的转换序列是一个按下述规格形成的序列&#xff1a; 1. 序列中第一个字符串是 beginStr。 2. 序列中最后一个字符串是 endStr。 3. 每次转换只能改变一个字符。 4. 转换过…

数据结构-时间、空间复杂度-详解

数据结构-时间复杂度-详解 1.前言1.1数据结构与算法1.2如何衡量一个算法的好坏1.3复杂度 2.时间复杂度2.1是什么2.2大O符号只保留最高阶项不带系数常数次为O(1) 2.3示例示例2.1示例2.2示例2.3示例2.4 2.4题目 3.空间复杂度3.1是什么3.2大O符号3.3示例示例1示例2示例3示例4 4.题…

用4种不同视角理解矩阵乘法

目录 1. 背景 2. 线性方程组视角&#xff08;向量点积视角&#xff09; 3. 列向量观点视角 4. 向量变换视角&#xff08;矩阵函数&#xff09; 5. 坐标变换视角 1. 背景 矩阵诞生于线性方程组的求解&#xff0c;最基本的运算方法来自于高斯消元法&#xff0c;所以矩阵整个…

一些问题的解决方案【持续更新ing】

一些问题的解决方案【持续更新ing】 WindowsCUDA 安装失败解决方案VS 添加现有项无反应无法定位程序输入点 于动态链接库 xxx.exe 上不同工具集生成的库无法通用更改只读属性 UbuntuVTK cmake 过程中找不到QT5目录Ubuntu添加环境变量&#xff08;永久最简单&#xff09;Wandb强…

书橱系统小程序的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;图书信息管理&#xff0c;图书类型管理&#xff0c;电子书论坛&#xff0c;系统管理 微信端账号功能包括&#xff1a;系统首页&#xff0c;图书信息&#xff0c;电子书论坛&#xff0c;我的 开发系统…