欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

C++之标准模板库STL

程序员文章站 2022-07-12 18:00:06
...

STL概述:可分为容器,迭代器,空间配置器,适配器,算法,仿函数六大组件。
容器:允许我们重复使用利用已有的实现构造自己的特定类型数据结构。通过设置一些模板类,STL容器对最常用的数据结构提供了支持,这些模板参数允许我们的指定的容器中元素的数据类型,可以将工作简化。
容器中部分
头文件
有:,,,,,,等组成。
vector:向量。 连续存储的元素。
list:列表。 由结点组成的双向链表,每个结点包含一个元素
deque:双队列。 由连续存储的指向不同元素的指针组成的数组
set:集合 由节点组成的红黑树,每个结点都包含一个元素,结点之间以某种作用于元素对的位于排列。
multiset:多重集合 允许存在两个次序相等的元素集合。
stack:栈 后进先出的值的排列
queue:队列。 先进先出的值的排列
priority_queue:优先队列 。 元素次序是作用于所存储的值对上的某种谓语决定的队列
map:映射 由对组成的集合,以某种作用于键对上的谓语排列。
multimap:多重映射。 允许键对有相同的次序映射。

常用的容器:
string:封装了char*
string类的构造函数:
string(); //默认构造参数
string(const string &str); //默认拷贝构造函数
string(const char *s); //使用字符串s初始化
string(int n,char c); //用n个字符串初始化

string类的遍历:
const char &operator[ ](int n) const;
const char &at(int n)const;
char &operator[ ](int n);
char &at(int n);
容器类型: :iterator it;
每个类型容器都会提供begin()和end()来获取一个迭代器。有点类似于指针。
(1)begin()函数获取的是一个指向容器第一个元素的迭代器
(2)end()函数获取的是一个指向容器的最后一个元素的迭代器。

string类的查找与替换:
int find(char c,int pos=0) const; //从pos查找字符c在当前字符串的位置
string &replace (int p0,int n0,const char *s,int n);删除p0开始的的n0个字符,然后在p0处插入字符串s的前几个字符。

string类的插入和删除
string &insert(int p0,const char *s); //在p0处插入字符串s
string &insert(int p0,const string &s); //在p0处插入字符串s

iterator erase(iterator first,iterator last) //删除[ first,last)之间的所有字符,返回删除后迭代器的位置
iterator erase(iterator it); //删除it指向的字符,返回删除后迭代器的位置

#include
#include
#include
#include
#include

using namespace std;

void string_init()
{
string s1; //无参构造函数
string s2(“helloworld”);
string s3(10, ‘a’);
string s4(s3);

cout << s1 << endl;
cout << s2 << endl;
cout << s3 << endl;
cout << s4 << endl;

}

void string_at()
{
string s1(“helloworld”);

//cout << s1[50000000] << endl;  //不安全
try
{
	cout << s1.at(10) << endl;   //运行出错会抛出异常
}
catch(exception &e)
{
	cout << "at 异常" << endl;
	cout << e.what() << endl;
}

}

void string_str()
{
string s(“helloworld”);
const char *ptr = s.c_str();
cout << ptr << endl;
}

void string_copy()
{
string s(“hellworld”);
char buf[32] = {0};
//s.copy(buf, 5, 3);
s.copy(buf, 5);
cout << buf << endl;
}

void string_length()
{
string s(“helloworld”);
cout << s.length() << endl;

if (s.empty())
{
	cout << "empty" << endl;
}
else
{
	cout << "not empty" << endl;
}

}

void string_assign()
{
string s1(“helloworld”);
string s2(“12345”);
string s3;

s3 = s2;
cout << s3 << endl;

s1.assign(s2);
cout << s1 << endl;

s1.assign(10, 'a');
cout << s1 << endl;

s1.assign("1234567890", 7);
cout << s1 << endl;

s1.assign(s2, 1, 3);
cout << s1 << endl;

}

void string_compare()
{
string s(“helloworld”);
string s2(“helloaaaaa”);

if (s.compare(s2) > 0)
{
	cout << "s > s2" << endl;
}
else
{
	cout << "s <= s2" << endl;
}

if (s.compare("aaaaa") > 0)
{
	cout << "s > aaaaa" << endl;
}
else
{
	cout << "s <= aaaaa" << endl;
}

}

void string_substr()
{
string s1(“helloworld”);
string s2;

s2 = s1.substr();
cout << s2 << endl;

s2 = s1.substr(4, 3);
cout << s2 << endl;

}

void string_find()
{
string s1(“helloworld”);
string s2(“owo”);
//int index = s1.find(‘o’);
//int index = s1.find(‘o’, 5);
int index = s1.find(‘o’, 7);
cout << index << endl;

index = s1.find("world", 1);
cout << index << endl;
index = s1.find(s2, 0);
cout << index << endl;

index = s1.rfind('l', 6);
cout << index << endl;

s1.replace(0, 5, "xx");
cout << s1 << endl;

string s3("helloworldhelloworldhelloworldhelloworld");
index = s3.find("hello");
while (index != -1)
{
	s3.replace(index, strlen("hello"), "xx");
	index = s3.find("hello", index + strlen("xx"));
}
cout << s3 << endl;

}

void string_insert()
{
string s1(“helloworld”);
string s2(“abcd”);

s1.insert(1, "aaa");
cout << s1 << endl;

s1.insert(5, s2);
cout << s1 << endl;

s1.insert(1, 10, 'x');
cout << s1 << endl;

s1.erase(1, 20);
cout << s1 << endl;

}

void string_transform()
{
string s1(“aaaaaBBBBBB”);
transform(s1.begin(), s1.end(), s1.begin(), ::toupper);
cout << s1 << endl;
}

int main()
{
//string_init();
//string_at();
//string_str();
//string_copy();
//string_length();
//string_assign();
//string_compare();
//string_substr();
//string_find();
//string_insert();
string_transform();
return 0;
}

vector容器
:将元素置于一个动态数组中加以管理的容器,可以随机存取元素,支持[ ]操作符,或者at()方法直接存取。
vector的初始化
vector c 产生空的vector
vector c1(c2)产生同类型的c1,并复制c2所有元素
vector c(n)利用类型T的默认构造函数和拷贝构造函数生成一个大小为n的vector
~vector ()销毁所有元素并释放内存

vector的非变动性操作
c.size(); 返回元素个数
c.empty(); 判断容器是否为空
c.reserve(n) 扩大容量为n

vector容器的赋值
c1 =c2; 将c2的全部元素赋给c1;
c.assign(n,e)将元素e的n个拷贝赋值给c
c1.swap(c2)将c1和c2的值交换

at(idx) 返回索引idx所标记元素的引用,进行越界检查
front()返回第一个元素的引用,不检查元素是否存在
back()返回最后一个元素的引用,不检查元素是否存在。

vector的插入与删除
c.insert(pos,e) 在pos位置插入元素e的副本,并返回新元素位置。
c.push_back(e) 在尾部添加一个元素e的副本
c.pop_back() 移除最后一个元素但不返回最后一个元素
c.erase(pos) 删除pos位置的元素,返回下一个元素的位置
c.clear() 移除所有元素,清空容器
c.resize(num) 将元素数量改为num

代码如下:
#include
#include

using namespace std;

int main()
{
int a[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 0};
vector v1;
vector v2(10, 10);
vector v3(a, a + 10);

for (int i = 0; i < v2.size(); i++)
{
	cout << v2[i] << " ";
}
cout << endl;

for (int i = 0; i < v3.size(); i++)
{
	cout << v3.at(i) << " ";
}
cout << endl;

v1.resize(10);
for (int i = 0; i < v2.size(); i++)
{
	v1[i] = v2[i];
}

for (int i = 0; i < v1.size(); i++)
{
	cout << v1[i] << " ";
}
cout << endl;

cout << v1.front() << endl;
cout << v1.back() << endl;

v1.front() = 100;
v1.back() = 100;
for (int i = 0; i < v1.size(); i++)
{
	cout << v1[i] << " ";
}
cout << endl;

v1.assign(a, a + 10);
for (int i = 0; i < v1.size(); i++)
{
	cout << v1[i] << " ";
}
cout << endl;

v1.assign(20, 1);
for (int i = 0; i < v1.size(); i++)
{
	cout << v1[i] << " ";
}
cout << endl;

v1.resize(30);
for (int i = 0; i < v1.size(); i++)
{
	cout << v1[i] << " ";
}
cout << endl;

v1.resize(5);
for (int i = 0; i < v1.size(); i++)
{
	cout << v1[i] << " ";
}
cout << endl;

//使用迭代器遍历数组  正向迭代器
//begin()指向vector的第一个元素 end()指向vector最后一个元素的后一个位置
for (vector<int>::iterator it = v3.begin(); it != v3.end(); it++)
{
	cout << *it << " ";
}
cout << endl;

//反向迭代器
for (vector<int>::reverse_iterator rit = v3.rbegin(); rit != v3.rend(); rit++)
{
	(*rit)++;
	cout << *rit << " ";
}
cout << endl;

//只读迭代器
for (vector<int>::const_iterator cit = v3.begin(); cit != v3.end(); cit++)
{
	//(*cit)++;
	cout << *cit << " ";
}
cout << endl;

v3.insert(v3.begin(), 100);
for (vector<int>::iterator it = v3.begin(); it != v3.end(); it++)
{
	cout << *it << " ";
}
cout << endl;

v3.insert(v3.begin(), 10, 20);
for (vector<int>::iterator it = v3.begin(); it != v3.end(); it++)
{
	cout << *it << " ";
}
cout << endl;

v3.insert(v3.end(), a, a + 10);
for (vector<int>::iterator it = v3.begin(); it != v3.end(); it++)
{
	cout << *it << " ";
}
cout << endl;

v3.erase(v3.begin());
for (vector<int>::iterator it = v3.begin(); it != v3.end(); it++)
{
	cout << *it << " ";
}
cout << endl;

v3.erase(v3.begin(), v3.begin() + 5);
for (vector<int>::iterator it = v3.begin(); it != v3.end(); it++)
{
	cout << *it << " ";
}
cout << endl;

v3.clear();
for (vector<int>::iterator it = v3.begin(); it != v3.end(); it++)
{
	cout << *it << " ";
}
cout << endl;

return 0;

}

deque容器
:双端数组,也是可以随机存取元素,支持索引值直接存取,可用[ ]操作符和at()方法。

deque容器的构造拷贝和析构
deque c 产生空的deque
deque c1(c2) 产生同类型的c1,并复制c2的所有元素
deque c(n)利用类型T的默认构造参数和拷贝构造参数生成一个大小为n的deque
~deque () 销毁所有元素并释放内存

deque的非变动性操作:
c.size(); 返回元素个数
c.empty(); 判断容器是否为空

deque的赋值操作
c1 =c2; 将c2的全部元素赋给c1;
c.assign(n,e)将元素e的n个拷贝赋值给c
c1.swap(c2)将c1和c2的值交换

deque的元素存取:
at(idx) 返回索引idx所标记元素的引用,进行越界检查
front()返回第一个元素的引用,不检查元素是否存在
back()返回最后一个元素的引用,不检查元素是否存在。

deque的插入与删除元素:
c.insert(pos,e) 在pos位置插入元素e的副本,并返回新元素位置。
c.push_back(e) 在尾部添加一个元素e的副本
c.pop_(front) 移除第一个元素但不返回最后一个元素
c.erase(pos) 删除pos位置的元素,返回下一个元素的位置
c.clear() 移除所有元素,清空容器
c.resize(num) 将元素数量改为num

代码如下:
#include
#include

using namespace std;

int main()
{
char ptr[] = “helloworld”;

deque<char> d1;
deque<char> d2(10, 'x');
deque<char> d3(ptr, ptr + strlen(ptr));

for (deque<char>::iterator it = d2.begin(); it != d2.end(); it++)
{
	cout << *it;
}
cout << endl;

for (deque<char>::iterator it = d3.begin(); it != d3.end(); it++)
{
	cout << *it;
}
cout << endl;

d2.push_back('y');
d2.push_front('y');
for (deque<char>::iterator it = d2.begin(); it != d2.end(); it++)
{
	cout << *it;
}
cout << endl;

d2.pop_back();
d2.pop_front();
for (deque<char>::iterator it = d2.begin(); it != d2.end(); it++)
{
	cout << *it;
}
cout << endl;

cout << d3[1] << endl;
cout << d3.at(2) << endl;

d2.insert(d2.begin(), 'Y');
d2.insert(d2.end(), 2, 'Y');
for (deque<char>::iterator it = d2.begin(); it != d2.end(); it++)
{
	cout << *it;
}
cout << endl;

d2.insert(d2.begin(), ptr, ptr + strlen(ptr));
for (deque<char>::iterator it = d2.begin(); it != d2.end(); it++)
{
	cout << *it;
}
cout << endl;

deque<char>::iterator it;
it = d2.erase(d2.begin());
for (deque<char>::iterator it = d2.begin(); it != d2.end(); it++)
{
	cout << *it;
}
cout << endl;
cout << *it << endl;
it = d2.begin();
cout << *it << endl;

it = d2.erase(d2.end() - 5, d2.end());
for (deque<char>::iterator it = d2.begin(); it != d2.end(); it++)
{
	cout << *it;
}
cout << endl;


return 0;

}

list容器:
是一个双向链表容器。可以有效的进行插入删除元素。但是不可以随机存取元素,所以不支持at(pos)函数和[ ]操作符
也不支持迭代器的随机访问

list容器的构造拷贝和析构
list c 产生空的deque
list c1(c2) 产生同类型的c1,并复制c2的所有元素
list c(n)利用类型T的默认构造参数和拷贝构造参数生成一个大小为n的deque
~list () 销毁所有元素并释放内存

list的非变动性操作:
c.size(); 返回元素个数
c.empty(); 判断容器是否为空

list的非赋值操作
c1 =c2; 将c2的全部元素赋给c1;
c.assign(n,e)将元素e的n个拷贝赋值给c
c1.swap(c2)将c1和c2的值交换

list的元素存取:
at(idx) 返回索引idx所标记元素的引用,进行越界检查
front()返回第一个元素的引用,不检查元素是否存在
back()返回最后一个元素的引用,不检查元素是否存在。

list的插入与删除元素:
c.insert(pos,e) 在pos位置插入元素e的副本,并返回新元素位置。
c.push_back(e) 在尾部添加一个元素e的副本
c.pop_(front) 移除第一个元素但不返回最后一个元素
c.erase(pos) 删除pos位置的元素,返回下一个元素的位置
c.clear() 移除所有元素,清空容器
c.resize(num) 将元素数量改为num

#include
#include

using namespace std;

class Person
{
private:
static int num;
int id;
string name;
string tel;
int age;
public:
Person(string n, string t, int a);
void showinfo() const;
};

int Person::num = 0;

Person::Person(string n, string t, int a)
{
num++;
id = num;
name = n;
tel = t;
age = a;
}

void Person::showinfo() const
{
cout << id << " " << name << " " << tel << " " << age << endl;
}

int main()
{
list l;

Person p1("aaaa", "111111", 20);
Person p2("bbbb", "222222", 20);
Person p3("cccc", "333333", 20);
Person p4("dddd", "444444", 20);
Person p5("eeee", "555555", 20);
Person p6("ffff", "666666", 20);

l.push_back(p1);
l.push_back(p2);
l.push_front(p3);
l.push_front(p4);
l.insert(l.begin(), p5);
l.insert(++l.begin(), p6);

for (list<Person>::iterator it = l.begin(); it != l.end(); it++)
{
	it->showinfo();
}

l.reverse();
for (list<Person>::iterator it = l.begin(); it != l.end(); it++)
{
	it->showinfo();
}

return 0;

}

map容器:
标准的关联式容器,一个map就是一个键值对序列即(key,value)对,提供了基于key的快速检索能力
map容器的构造拷贝和析构
map c 产生空的deque
map c1(c2) 产生同类型的c1,并复制c2的所有元素
~map () 销毁所有元素并释放内存

map的非变动性操作:
c.size(); 返回元素个数
c.empty(); 判断容器是否为空

map的赋值操作
c1 =c2; 将c2的全部元素赋给c1;
c1.swap(c2)将c1和c2的值交换

map的插入,数据查找与删除元素:
map <int ,string> m,
count(key) //返回值等于key的元素个数
find(key) 返回值等于key的第一个元素,找不到返回end
upper_bound(key) 返回值大于key的第一个元素
equal_bound(key) 返回值等于key的元素区间

c.erase(beg,end) 删除[beg,end]内的元素,无返回值
c.clear() 移除所有元素,清空容器

stack(栈)的部分代码
#include
#include

using namespace std;

int main()
{
stack s;

for (int i = 0; i < 10; i++)
{
	s.push(i + 1);
}

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

while (!s.empty())
{
	cout << s.top() << " ";
	s.pop();
}
cout << endl;

return 0;

}

queue(队列)的部分代码:
#include
#include

using namespace std;

int main()
{
queue q;

for (int i = 0; i < 10; i++)
{
	q.push(i + 1);
}

cout << q.front() << endl;
cout << q.back() << endl;

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

return 0;

}