Vector
vector数据结构和数组非常相似 ,也称为单端数组 , 与数组不同在于 数组是静态空间,而vector可以动态扩展 , 动态扩展不是在原有空间之后续接空间,而是找更大的内存空间,将原数据拷贝到新空间,释放原空间。
构造方式
//vector
构造方式
vector<int>v1;//默认,无参构造
vector<int>v2(v1.begin(), v1.end());//通过区间的方式进行构造
vector<int>v3(5, 20);//n个elem构造
vector<int>v4(v2);//拷贝构造
赋值操作
重载 = 运算符 assign(beg , end) assign(n , elem)
写一个打印容器里元素的代码
void printvector(vector<int> & v)
{
for(vector<int>::iterator it = v.begin() ; it != v.end() ; it++)
{
cout << *it << " " ;
}
cout << endl;
}
void test01()
{
vector<int>v1;//默认 , 无参
for (int i = 0; i < 10; i++)
{
v1.push_back(i);
}
printvector(v1);
vector<int>v2 = v1;
printvector(v2);
vector<int>v3;
v3.assign(v2.begin(), v2.end());
printvector(v3);
vector<int>v4;
v4.assign(4, 24);
printvector(v4);
}
vector容器容量和大小操作
使用capacity和size函数
1、empty() 判断容器是否为空 capacity() 容量
2、size()元素个数
3、resize(int num) 重新指定长度,变长 默认值填充,变短就删除
4、resize(int num ,elem) 重新指定长度num 若容器变长用elem填充 ,变短则删除后面元素
void test01()
{
vector<int>v1;
for (int i = 0; i < 10; i++)
{
v1.push_back(i);
}
printvector(v1);
if (v1.empty()) //为真 , 容器为空
{
return;
}
else
{
cout << v1.size() << endl;
cout << v1.capacity() << endl;
}
v1.resize(15);//默认0填充(15,100)100填充
printvector(v1);
v1.resize(8);
printvector(v1);
}
删除 插入
1、push_back()
2、pop_back()
3、insert(const_iterator pos , ele) 第一个参数需要提供一个迭代器
4、insert(const_iterator pos ,int count, ele)第一个参数需要提供一个迭代器
5、erase(const_iterator pos)第一个参数需要提供一个迭代器
6、erase(const_iterator start , const_iterator end)
7、clean()
void test01()
{
vector<int>v1;
for (int i = 0; i < 10; i++)
{
v1.push_back(i);
}
v1.pop_back();
printvector(v1);
v1.insert(v1.begin(), 100);//第一个参数需要提供一个迭代器
printvector(v1);
v1.insert(v1.begin(), 2, 1000);
printvector(v1);
v1.erase(v1.begin());//位置迭代器
printvector(v1);
//v1.erase(v1.begin(),v1.end());
v1.clear();
printvector(v1);
}
数据存储
1、at(int idx)
2、operator[]
3、front()返回容器中第一个数据元素
4、back()返回最后一个元素
void test01()
{
vector<int>v1;
for (int i = 0; i < 10; i++)
{
v1.push_back(i);
}
for (int i = 0; i < v1.size(); i++)
{
//cout << v1[i] << " ";
cout << v1.at(i) << " ";
}
cout << endl;
}
互换容器
swap(vec) 将vec和本身的元素互换
这个函数有点意思,巧用可以收缩内存空间
void test02()
{
/*vector<int>v;
for (int i = 0; i < 100000; i++)
{
v.push_back(i);
}*/
cout <<"v的容量:" << v.capacity() << endl;
cout << "v的大小:" << v.size() << endl;
v.resize(3);//容量不变
cout << "v的容量:" << v.capacity() << endl;
cout << "v的大小:" << v.size() << endl;
//巧用swap 底层vector<int>(v)是匿名对象 匿名函数的特点 当前函数执行完之后就回收内存
vector<int>(v).swap(v);
cout << "v的容量:" << v.capacity() << endl;
cout << "v的大小:" << v.size() << endl;
}
vector<int>(v).swap(v);
该方法的底层逻辑是上述这行代码,当我原始有一个很长的数组,然后通过resize将数组变成很短,那么该数组的容量是不会变的,当使用这一行代码的时候,会先创建vector<int>(v)这一个匿名函数,是用v赋值 给这个匿名函数,所以匿名函数的大小和容量就是v.size(),然后再使用swap函数进行交换,这时候就将匿名函数的内容和v进行交换,那么v.capacity()也就变小了。由于匿名函数本身的特点,当前函数执行完之后系统就会自动收回其内存,这样就不用担心内存泄漏了。
vector预留空间
reserve(int len);容器预留len个长度,预留位置不初始化,元素不可访问
void test02()
{
vector<int>v;
//利用reserve预留空间
v.reserve(100000);
int num = 0;//统计开辟次数
int* p = NULL;
for (int i = 0; i < 100000; i++)
{
v.push_back(i);
if (p != &v[0])
{
p = &v[0];
num++;
}
}
cout << "Num = " << num << endl; //没使用reserve的时候num的大小是30 当使用了reserve的时候num为1.
}
没使用reserve的时候num(开辟次数)的大小是30 当使用了reserve的时候num为1。
string
string是C++风格的字符串 , 而string本质上是一个类。
string 和 char* 的区别:string是一个类,类内部封装了char* ,是一个char*型的容器。
特点:string内部封装了很多成员方法,eg find、copy、delete、replace、insert , string管理char*所分配的内存。
构造方式
1、string()
2、string(const char* s)
3、string(const string&str)
4、string(int n ,char c)
void test02()
{
string s1;
const char* str = "hello world";
string s2(str);
cout << s2 << endl;
string s3(s2);
cout << "S3= " << s3 << endl;
string s4(10, 'a');
cout << s4 << endl;
}
赋值操作
1、string& operator=(const char* s);
2、string& operator=(const string&s);
3、string& operator=(char c );
4、string& assign(const char*s)
5、string& assign(const char*s , int n )
6、string& assign(const string&s)
字符串拼接 (实现在字符串末尾拼接字符串)
1、string& operator+=(const char* s);
2、string& operator+=(const string&s);
3、string& operator+=(char c );
4、string& append(const char*s) // 连接到结尾
5、string& append(const char*s , int n )//前n个字符连接到结尾
6、string& append(const string&s)
7、string& append(const string&s , int pos , int n );//从pos开始的n字符连接到结尾
void test01()
{
string str1;
str1 = "hello world";
cout << "str1 = " << str1 << endl;
string str2;
str2.assign(str1);
string str3;
str3 = "我爱玩游戏:";
string str4 = "LOL";
str3 += str4;
cout << str3 << endl;
string str5 = "DNF";
str3.append(str5);
cout << str3 << endl;
str3.append("game abcde", 4);
cout << str3 << endl;
str3.append("LOL DNF", 4, 3);
cout << str3 << endl;
}
字符串查找替换
find() rfind()
rfind 和find区别: rfind从右往左查找 find 从左往右查找。
void test01()
{
string str1 = "abcdefde";
int pos = str1.find("de"); // 返回下标位置 如果没找到返回-1
cout << pos << endl;
//rfind 和find区别 rfind从右往左查找 find 从左往右查找
pos = str1.rfind("de");
cout << pos << endl;
}
void test02()
{
string str1 = "abcdefg";
str1.replace(1, 3, "1111");//从1号位置起 3 个字符替换
cout << str1 << endl;//a1111efg
}
比较
字符串比较是按字符的ascii码进行对比 = 返回 0; > 返回 1 ; < 返回 -1
compare()
字符存取
1、通过[]方式取字符char& operator[](int n )
2、char& at(int n )通过at方法获取
void test02()
{
string str = "hello";
/*cout << str[1] << endl;
cout << str.at(2) << endl;*/
for (int i = 0; i < str.size(); i++)
{
//cout << str[i] <<" " ;
cout << str.at(i) << " ";
}
cout << endl;
//修改
str[0] = 'x';
cout << str << endl;
}
插入 insert 删除erase
void test02()
{
string str = "hello";
str.insert(1, "111");
cout << str << endl;//h111ello
str.erase(1, 3);
cout << str << endl;
}
string子串
获取想要的子串 substr(int pos = 0 ,int n = npos) 返回由pos开始的n个字符串,该方法一般常和find一起使用,比如说获取邮件中人的信息等
void test01()
{
string email ="zhangsan@163.com";
string name = substr(0 , email.find('@'));
cout << name << endl;
}