一、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;
}