0904,关联式容器针对于自定义形式的写法(
目录
001_set.cc
002_set.cc 坏,我就说怎么想着不对嘻嘻
003_setAA_Person.cc
作业
01 list拥有哪些特有的操作,其功能是什么,请举例说明。
02 问答题:STL中的emplace_back和push_back有什么区别?提示:可以从构建方式、性能等方面作答。
03 自己独立实现出set针对于Point的三种写法
04 题目:计算集合的并集:描述:给你两个集合,计算其并集,即 {A} + {B}。注:不允许出现重复元素,但是 {A} 与 {B}之间可能存在相同元素。
001_set.cc
#include <iostream>
#include <vector>
#include <deque>
#include <string.h>
#include <random>
#include <set>
using std::cout;
using std::endl;
using std::vector;
using std::deque;
using std::ostream;
using std::set;
using std::pair;
template <typename Container>
void display(const Container & con){
for(auto &ele: con){
cout<<ele<<" ";
}
cout<<endl;
}
void test(){
set<int>num{1,2,3,4,5,6,66,6,6,7,7,7};
display(num);
set<int,std::greater<int>>num1{1,2,3,4,5,6,66,6,6,7,7,7};
display(num1);
//---------------------------------//
//erase(pos,[pos,pos),)
//---------------------------------//
cout<<endl<<"set: erase"<<endl;
num.erase(++num.begin());
display(num);
cout<<endl<<"set is not support []"<<endl;
/* cout<<num[4]<<endl; */
cout<<endl<<"set can change *it"<<endl;
auto it =++num.begin();
/* *it=9000; */
//不支持使用迭代器进行修改,会导致元素重排(红黑树实现)
//影响红黑树的稳定性
}
int main(void)
{
test();
return 0;
}
002_set.cc 坏,我就说怎么想着不对嘻嘻
#include <iostream>
#include <vector>
#include <deque>
#include <string.h>
#include <random>
#include <set>
using std::cout;
using std::endl;
using std::vector;
using std::deque;
using std::ostream;
using std::set;
using std::pair;
template <typename Container>
void display(const Container & con){
for(auto &ele: con){
cout<<ele<<" ";
}
cout<<endl;
}
void test(){
/* set<int>nnum{1,2,3,7,9,11,4,5,6,66,6,6,7,7,7}; */
set<int>nnum{1,3,5,7,8,2,3,4,455,555,22,2,666,777,888};
display(nnum);
//delete single_nnum
for(auto it=nnum.begin();it!=nnum.end();){
//不能在for循环里面++,会漏掉
if(*it&1){
/* nnum.erase(it++); */
//1
/* auto temp=it; */
/* it++; */
/* nnum.erase(temp); */
//删除的迭代器会失效,其他的不受影响(like array)
//2
it=nnum.erase(it);
//更加通用
}else{
it++;
}
}
display(nnum);
}
int main(void)
{
test();
return 0;
}
003_setAA_Person.cc
#include <iostream>
#include <vector>
#include <deque>
#include <string.h>
#include <set>
#include <random>
#include <math.h>
using std::cout;
using std::endl;
using std::set;
using std::vector;
using std::deque;
using std::ostream;
//-------------------------------------//
template <typename Container>
void display(const Container & con){
for(auto &ele: con){
cout<<ele<<" ";
}
cout<<endl<<endl;
}
//-------------------------------------//
class AA{
public:
/* AA() */
/* :_aa(0),_bb(0) */
/* {cout<<"AA()"<<endl;} */
AA(int a=0,int b=0)
:_aa(a),_bb(b)
{cout<<"AA(int ,int)"<<endl;}
AA(const AA & a)
:_aa(a._aa),_bb(a._bb)
{cout<<"AA(const AA &)"<<endl;}
AA(const AA && a)
:_aa(a._aa),_bb(a._bb)
{cout<<"AA(const AA &&)"<<endl;}
double get_distance ()const{
return hypot(_aa,_bb);
}
int geta()const{return _aa;}
int getb()const{return _bb;}
friend ostream & operator<<(ostream & os,const AA & p);
private:
int _aa;
int _bb;
};
ostream & operator<<(ostream & os,const AA & p){
os<<p._aa<<"--"<<p._bb<<" ";
return os;
}
//-------------------------------------//
//函数运算符重载
//-------------------------------------//
bool operator<(const AA & a,const AA & p){
cout<<"operator <<<"<<endl;
if(a.get_distance()!=p.get_distance()){
return a.get_distance()<p.get_distance();
}else{
if(a.geta()!=p.geta()){
return a.geta()<p.geta();
}else{
return a.getb()<p.getb();
}
}
}
bool operator>(const AA & a,const AA & p){
cout<<"operator >>>"<<endl;
if(a.get_distance()!=p.get_distance()){
return a.get_distance()>p.get_distance();
}else{
if(a.geta()!=p.getb()){
return a.geta()>p.geta();
}else{
return a.getb()>p.getb();
}
}
}
//-------------------------------------//
//函数对象的方式
//-------------------------------------//
struct CompareAA{
bool operator()(const AA & a,const AA & p)const{
cout<<"struct CompareAA"<<endl;
if(a.get_distance()!=p.get_distance()){
return a.get_distance()<p.get_distance();
}else{
if(a.geta()!=p.getb()){
return a.geta()<p.geta();
}else{
return a.getb()<p.getb();
}
}
}
};
//-------------------------------------//
//命名空间的扩展(模板特化)
//-------------------------------------//
namespace std{
template <>
struct less<AA>{
bool operator()(const AA & a,const AA & p)const{
cout<<"namespace std::: less<>"<<endl;
if(a.get_distance()!=p.get_distance()){
return a.get_distance()<p.get_distance();
}else{
if(a.geta()!=p.getb()){
return a.geta()<p.geta();
}else{
return a.getb()<p.getb();
}
}
}
};
template <>
struct greater<AA>{
bool operator()(const AA & a,const AA & p)const{
cout<<"namespace std::: greater<>"<<endl;
if(a.get_distance()!=p.get_distance()){
return a.get_distance()>p.get_distance();
}else{
if(a.geta()!=p.getb()){
return a.geta()>p.geta();
}else{
return a.getb()>p.getb();
}
}
}
};
}//end of namespace std
//-------------------------------------//
//-------------------------------------//
class Person{
public:
/* Person() */
/* :_name(new char[5]()),_score(0) */
/* { */
/* strcpy(_name,"haha"); */
/* cout<<"Person()"<<_name<<endl; */
/* } */
Person(const char* name="xixi",const int sc=0)
:_name(new char[strlen(name)+1]()),_score(sc)
{
strcpy(_name,name);
cout<<"Person(char* ,int)"<<endl;
}
Person(const Person & p)
:_name(new char[strlen(p._name)+1]()),_score(p._score)
{
strcpy(_name,p._name);
cout<<"Person(const Person &)"<<endl;
}//vector初始化使用拷贝构造
~Person(){
if(_name){
delete [] _name;
_name=nullptr;
}
}
Person & operator=(const Person & p){
if(this!=&p){
delete [] _name;
_name=new char[strlen(p._name)+1]();
strcpy(_name,p._name);
_score=p._score;
}
return *this;
}
void p_sc(int sc){
_score=sc;
}
int getsc ()const{return _score;}
char* getname()const{return _name;}
friend ostream & operator<<(ostream & os,const Person & p);
private:
char* _name;
int _score;
};
ostream & operator<<(ostream & os,const Person & p){
os<<p._name<<"--"<<p._score<<" ";
return os;
}
bool operator<(const Person & a,const Person & b){
if(a.getsc()!=b.getsc()){
return a.getsc()<b.getsc();
}else{
return a.getname()<b.getname();
}
}
bool operator>(const Person & a,const Person & b){
if(a.getsc()!=b.getsc()){
return a.getsc()>b.getsc();
}else{
return a.getname()>b.getname();
}
}
//-------------------------//
//-------------------------//
struct ComparePerson{
bool operator()(const Person & a,const Person & b)const{
if(a.getsc()!=b.getsc()){
return a.getsc()>b.getsc();
}else{
return a.getname()>b.getname();
}
}
};
//-------------------------//
//-------------------------//
namespace std{
template <>
struct less<Person>{
bool operator()(const Person & a,const Person & b)const{
if(a.getsc()!=b.getsc()){
return a.getsc()<b.getsc();
}else{
return a.getname()<b.getname();
}
}
};
template <>
struct greater<Person>{
bool operator()(const Person & a,const Person & b)const{
if(a.getsc()!=b.getsc()){
return a.getsc()>b.getsc();
}else{
return a.getname()>b.getname();
}
}
};
}//end of namespace std
//-------------------------//
//-------------------------//
void test(){
set<int> n{3,36,34,6,4,8,34,2,8,58}; //默认排序
set<AA> num0{AA(1,1),AA(1,2),AA(-1,3),AA(2,2),AA(1,5)};
cout<<endl<<endl;
set<AA,std::greater<AA>> num1{AA(1,1),AA(2,2),AA(-1,3),AA(1,4),AA(1,5)};
cout<<endl<<endl;
set<AA,CompareAA> num2{AA(1,1),AA(1,2),AA(-1,3),AA(-2,4),AA(1,5)};
cout<<endl<<endl;
//坏,不放对象
set<Person> p0{Person("xixi",100),Person("kaixin",100),Person("jiajia",101),Person("lili",102)};
set<Person,std::greater<Person>> p1{Person("xixi",100),Person("kaixin",100),Person("jiajia",101),Person("lili",102)};
set<Person,ComparePerson> p2{Person("xixi",100),Person("kaixin",100),Person("jiajia",101),Person("lili",102)};
display(n);
cout<<"set<AA> num0"<<endl;
display(num0);
cout<<"set<AA,std::greater> num1"<<endl;
display(num1);
cout<<"set<AA,CompareAA> num2"<<endl;
display(num2);
cout<<"set<Person> num0"<<endl;
display(p0);
cout<<"set<Person,std::greater<Person>> num0"<<endl;
display(p1);
cout<<"set<Person,ComparePerson> num0"<<endl;
display(p2);
}
int main(void)
{
test();
return 0;
}
作业
01 list拥有哪些特有的操作,其功能是什么,请举例说明。
reverse unique sort emplace_back splice
#include <iostream>
#include <list>
#include <math.h>
using std::cout;
using std::endl;
using std::list;
using std::ostream;
//-------------------------------------//
template <typename Container>
void display(const Container & con){
for(auto &ele: con){
cout<<ele<<" ";
}
cout<<endl<<endl;
}
//-------------------------------------//
class AA{
public:
AA(int a=0,int b=0)
:_aa(a),_bb(b)
{}
double get_distance ()const{
return hypot(_aa,_bb);
}
int geta()const{return _aa;}
int getb()const{return _bb;}
friend ostream & operator<<(ostream & os,const AA & p);
private:
int _aa;
int _bb;
};
ostream & operator<<(ostream & os,const AA & p){
os<<p._aa<<"--"<<p._bb<<" ";
return os;
}
//-------------------------------------//
//函数运算符重载
//-------------------------------------//
bool operator<(const AA & a,const AA & p){
cout<<"operator <<<"<<endl;
if(a.get_distance()!=p.get_distance()){
return a.get_distance()<p.get_distance();
}else{
if(a.geta()!=p.geta()){
return a.geta()<p.geta();
}else{
return a.getb()<p.getb();
}
}
}
bool operator>(const AA & a,const AA & p){
cout<<"operator >>>"<<endl;
if(a.get_distance()!=p.get_distance()){
return a.get_distance()>p.get_distance();
}else{
if(a.geta()!=p.getb()){
return a.geta()>p.geta();
}else{
return a.getb()>p.getb();
}
}
}
bool operator==(const AA & a,const AA & p){
return (a.geta()==p.geta())&&(a.getb()==p.getb());
}
//-------------------------------------//
void test(){
list<AA> num0{AA(1,1),AA(1,1),AA(1,1),AA(1,1),AA(1,1),AA(1,2),AA(-1,3),AA(2,2),AA(1,5)};
list<AA> num1{AA(-8,3),AA(100,100),AA(5)};
display(num0);
num0.reverse();
display(num0);
num0.sort();
num0.unique();
display(num0);
num0.emplace_back(88,88);
display(num0);
num0.splice(num0.begin(),num1,--num1.end());//end()是最后一个元素的下一个位置
display(num0);
}
int main(void)
{
test();
return 0;
}
02 问答题:STL中的emplace_back和push_back有什么区别?提示:可以从构建方式、性能等方面作答。
0903,LIST(merge,splice,sort,unique),SET(insert,erase)-CSDN博客
代码实现:05 vec emplace back.cc
建构方式上,emplace_back(类的成员变量)接受构造对象需要的参数,直接在容器内部构件,只调用一次构造函数,push_back(匿名对象)则是会创建一个匿名对象,再调用移动构造和拷贝构造实现对象放入容器的过程
性能上,emplace_back 少了几次拷贝构造的开销比push_back更加高效
emplace_back直接在容器末尾构造元素,而push_back将元素复制或移动到容器末尾。
emplace_back通常更高效,因为它避免了不必要的复制。 `vector` 的 `push_back` 和 `emplace_back` 函数都是用来在 `vector` 的末尾添加新元素的,但它们之间有几个关键的区别:
1. **构造方式**:
2. `push_back` 函数会复制或移动已经构造好的对象到 `vector` 的末尾。
3. `emplace_back` 函数则是直接在 `vector` 的末尾构造新元素,它接受的是构造函数的参数,而不是对象本身。
4. **性能**:
5. 使用 `push_back` 时,如果传入的是一个临时对象,它首先会被构造,然后再被复制或移动到 `vector` 中(C++11起,会尝试使用移动构造减少开销)。
6. `emplace_back` 则可以避免这些额外的复制或移动操作,因为它直接在容器的内存中构造对象,从而可能提供更好的性能。
7. **例子**:
8. 使用 `push_back` 添加一个复杂对象时:`myVector.push_back(MyClass(a, b, c));` 这里 `a, b, c` 是传递给 `MyClass` 构造函数的参数,首先在外部构造一个临时的 `MyClass` 对象,然后将其添加到 `vector`。
9. 使用 `emplace_back` 相同的操作:`myVector.emplace_back(a, b, c);` 这里直接将参数 `a, b, c` 传递给 `emplace_back`,在 `vector` 的内存空间中直接构造对象,无需临时对象。
03 自己独立实现出set针对于Point的三种写法
003_setAA_Person.cc
04 题目:计算集合的并集:描述:给你两个集合,计算其并集,即 {A} + {B}。注:不允许出现重复元素,但是 {A} 与 {B}之间可能存在相同元素。
输入格式
输入数据分为三行,第一行有两个数字n,m(0 < n,m<=10000) ,分别表示集合A和集合B的元素个数。后两行分别表示集合 A 和集合 B。每个元素为不超出int范围的整数,每个元素之间用一个空格隔开。
输出格式
输出一行数据,表示合并后的集合,要求从小到大输出,每个元素之间用一个空格隔开。
样例输入1
1 2
1
2 3
样例输出1
1 2 3
样例输入2
1 2
1
1 2
样例输出2
1
#include <iostream>
#include <limits>
#include <set>
using std::cout;
using std::cin;
using std::endl;
using std::set;
using std::ostream;
template <class CompareAA>
void display(const CompareAA & con){
for(auto & ele:con){
cout<<ele<<" ";
}
cout<<endl;
}
void inputInt(std::istream & is ,int & num){
//逗号只取决于,逗号之前的最后一个表达式
while(is>>num,!is.eof()){
if(is.bad()){
cout<<"istream has broken"<<endl;
return ;
}else if(is.fail()){
cout<<"input an int"<<endl;
is.clear();
is.ignore(std::numeric_limits<std::streamsize>::max(),' ');
}else{
break;
}
}
}
void test(){
cout<<"input 2 jihe capacity"<<endl;
int cap1=0,cap2=0,cap3=0;
inputInt(cin,cap1);
inputInt(cin,cap2);
cap3=cap1+cap2;
set<int> ss;
while(cap3!=0){
inputInt(cin,cap1);
ss.insert(cap1);
cap3--;
}
display(ss);
}
int main(void)
{
test();
return 0;
}
#include <iostream> #include <set> using std::cout; using std::endl; using std::cin; using std::set; int main(){ set<int> res; int n, m; cin >> n >> m; int tmp; for(int i = 0; i < n; i++) { cin >> tmp; res.insert(tmp); } for(int i = 0; i < m; i++) { cin >> tmp; res.insert(tmp); } for(set<int>::iterator it = res.begin(); it != res.end(); ++it) { if(it == res.begin()) cout << (*it); else cout << " " << (*it); } return 0; }
好好好