当前位置: 首页 > news >正文

string和oj题以及vector的接口介绍

前言

上篇博客学习了一些string类的模拟实现erase、find、substr、比较大小、流输入、流输出,这篇博客将介绍剩下的一些string的知识以及vector的一些使用方式。

string

传统深拷贝的写法

//拷贝构造
string(const string& s)
{_str = new char[s._capacity + 1];strcpy(_str, s._str);_size = s._size;_capacity = s._capacity;
}//拷贝赋值
string& operator=(const string& s)
{if (this != &s){delete[] _str;_str = new char[s._capacity + 1];strcpy(_str,s._str);_size = s._size;_capacity = s._capacity;}return *this;
}

手动将字符串的空间进行调整

现代深拷贝的写法

void swap(string& s)
{std::swap(_str,s._str);std::swap(_size,s._size);std::swap(_capacity, s._capacity);
}
//拷贝构造
string(const string& s)
{string tmp(s._str);swap(tmp);
}
//拷贝赋值
string& operator=(const string& s)
{if (this != &s){string tmp(s);swap(tmp);}return *this;
}string& operator=(string s)
{swap(s);return *this;
}

在这里插入图片描述
利用swap将数据进行深拷贝
在这里插入图片描述
从中我们可以知道,string中的swap底层也是靠std中的swap实现的。

写时拷贝与引用计数

写时拷贝就是一种拖延症,是在浅拷贝的基础之上增加了引用计数的方式来实现的。
引用计数:用来记录资源使用者的个数。在构造时,将资源的计数给成1,每增加一个对象使用该资源,就给计数增加1,当某个对象被销毁时,先给该计数减1,然后再检查是否需要释放资源,如果计数为1,说明该对象时资源的最后一个使用者,将该资源释放;否则就不能释放,因为还有其他对象在使用该资源。
在这里插入图片描述
我们知道深拷贝存在的问题:

  1. 需要析构两次
  2. 一个数据修改了会影响另一个数据

而写时拷贝可以让一个数据被删除时,另一个数据不会被影响
在这里插入图片描述

oj题

反转字符串中的单词 III

反转字符串中的单词 III-力扣
在这里插入图片描述
思路:

  1. 利用find找空格的位置
  2. 利用reverse将每个词进行反转
  3. 最后利用rfind找到最后一个空格的位置,将最后一个词进行反转
class Solution {
public:string reverseWords(string s) {int end=s.find(" ");int begin=0;while(end != -1){reverse(s.begin()+begin,s.begin()+end);begin=end+1;end=s.find(" ",begin);}end=s.rfind(" ");reverse(s.begin()+end+1,s.end());return s;}
};

在这里插入图片描述

字符串相乘

字符串相乘-力扣
在这里插入图片描述
思路:
在这里插入图片描述

  1. 将两个字符串进行反转
  2. 创建数组,遍历将乘积存入数组
  3. 接着进行进位
  4. 最后将数组中的数字倒着进行输出即可
class Solution {
public:string multiply(string num1, string num2) {if(num1 == "0" || num2 == "0")return "0";reverse(num1.begin(),num1.end());reverse(num2.begin(),num2.end());int s1=num1.size(),s2=num2.size();int* ans=new int[s1+s2]{0};for(int i=0;i<s1;i++){for(int j=0;j<s2;j++){ans[i+j] +=(num1[i]-'0')*(num2[j]-'0');}}for(int i=0;i<s1+s2;i++){if(ans[i]>9){int t=ans[i];ans[i]=t%10;ans[i+1]+=(t/10);}}int pos=(ans[s1+s2-1] == 0 ? s1+s2-2:s1+s2-1);string s;for(;pos>=0;--pos){s+=(ans[pos]+'0');}return s;}
};

在这里插入图片描述

vector

vector接口介绍

  • vector的构造函数

⁂ 代表重点

vector的构造函数说明
vector()⁂无参构造
vector(size_type n, const value_type& val = value_type())构造并初始化n个val
vector((const vector& x)⁂拷贝构造
vector (InputIterator first, InputIterator last)使用迭代器进行构造
  • vector的输出方式

⁂ 代表重点

vector的输出方式说明
范围for从头到尾遍历
operator[] ⁂返回vector中n处的元素的引用
begin()+end() ⁂获取第一个数据位置的iterator 获取最后一个数据的下一个位置的iterator
rbegin()+rend()获取第一个数据位置的reverse_iterator, 获取最后一个数据的reverse_iterator
cbegin()+cend()获取第一个数据位置的const_iterator, 获取最后一个数据的下一个位置的const_iterator
crbegin()+crend()获取第一个数据位置的const_reverse_iterator, 获取最后一个数据的const_reverse_iterator
#include<iostream>
#include<vector>using namespace std;int main()
{vector<int> v;vector<int> v2(10, 2);for (auto i : v2){cout << i << " ";}cout << endl;vector<int> v4(v2);for (int i = 0; i < v4.size(); i++){cout << v4[i] << " ";}cout << endl;vector<int> v3(++v2.begin(), --v2.end());vector<int>::iterator it = v3.begin();while (it != v3.end()){cout << *it << " ";it++;}cout << endl;vector<int> v5(20, 3);vector<int>::reverse_iterator rit = v5.rbegin();while (rit != v5.rend()){cout << *rit << " ";rit++;}cout << endl;return 0;
}

在这里插入图片描述

  • vector的析构函数

在这里插入图片描述

  • operator= ⁂

将新内容分配给容器,替换其当前内容,并相应地修改其大小。
在这里插入图片描述

#include<iostream>
#include<vector>using namespace std;void vector_test2()
{vector<int> v1(10, 1);vector<int> v2(20, 2);for (auto i : v2){cout << i << " ";}cout << endl;v2 = v1;for (auto i : v2){cout << i << " ";}cout << endl;}int main()
{vector_test2();return 0;
}

在这里插入图片描述

  • vector 空间增长问题

⁂ 代表重点

容量空间接口说明
size ⁂获取数据个数
max_size获取数据最大个数
resize ⁂改变vector的size
capacity ⁂获取数据容量大小
empty判断是否为空
reserve ⁂改变vector的capacity
shrink_to_fit减小容量大小使其适应数据
#include<iostream>
#include<vector>using namespace std;void vector_test3()
{vector<int> v(15, 2);cout << v.size() << endl;cout << v.capacity() << endl;v.resize(5);cout << v.size() << endl;cout << v.capacity() << endl;v.resize(20);cout << v.size() << endl;cout << v.capacity() << endl;v.reserve(5);cout << v.size() << endl;cout << v.capacity() << endl;v.reserve(50);cout << v.size() << endl;cout << v.capacity() << endl;cout << v.empty() << endl;v.shrink_to_fit();cout << v.size() << endl;cout << v.capacity() << endl;}int main()
{vector_test3();return 0;
}

在这里插入图片描述
注意:

  1. reserve只负责开辟空间,如果确定知道需要用多少空间,reserve可以缓解vector增容的代价缺陷问题。
  2. resize在开空间的同时还会进行初始化,影响size。
#include<iostream>
#include<vector>using namespace std;void TestVectorExpand()
{size_t sz;vector<int> v;sz = v.capacity();cout << "making v grow:\n";for (int i = 0; i < 100; ++i){v.push_back(i);if (sz != v.capacity()){sz = v.capacity();cout << "capacity changed: " << sz << '\n';}}
}int main()
{TestVectorExpand();	return 0;
}

在这里插入图片描述
由此可知在vs2020的环境下,扩容的速度是1.5倍速

#include<iostream>
#include<vector>using namespace std;void TestVectorExpand()
{size_t sz;vector<int> v;sz = v.capacity();v.reserve(100);cout << "making v grow:\n";for (int i = 0; i < 100; ++i){v.push_back(i);if (sz != v.capacity()){sz = v.capacity();cout << "capacity changed: " << sz << '\n';}}
}int main()
{TestVectorExpand();	return 0;
}

在这里插入图片描述

  • vector的调整

⁂ 代表重点

vector的调整接口说明
assign分配vector内容
push_back ⁂尾插
pop_back ⁂尾删
insert在position之前插入val
erase删除position位置的val
swap交换两个vector的数据空间
clear清除vector的数据
#include<iostream>
#include<vector>using namespace std;void vecotr_test4()
{vector<int> v(10,5);v.assign(5, 4);for (auto i : v){cout << i << " ";}cout << endl;vector<int> v2(10, 2);v2.push_back(6);for (auto i : v2){cout << i << " ";}cout << endl;v2.pop_back();for (auto i : v2){cout << i << " ";}cout << endl;vector<int> v3(10,3);vector<int>::iterator it = v3.begin();v3.insert(it,2, 1);for (auto i : v3){cout << i << " ";}cout << endl;vector<int>::iterator it2 = v3.begin();v3.erase(it2,it2+2);for (auto i : v3){cout << i << " ";}cout << endl;vector<int> v4(10, 1);vector<int> v5(5, 2);for (auto i : v4){cout << i << " ";}cout << endl;for (auto i : v5){cout << i << " ";}cout << endl;swap(v4, v5);for (auto i : v4){cout << i << " ";}cout << endl;for (auto i : v5){cout << i << " ";}cout << endl;v5.clear();for (auto i : v5){cout << i << " ";}cout << endl;
}int main()
{vecotr_test4();return 0;
}

在这里插入图片描述

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • Redis五种基本数据结构的使用
  • 【设计模式】创建型模式(三):单例模式
  • oracle avg、count、max、min、sum、having、any、all、nvl的用法
  • OLED(3)字库篇
  • 图文深入理解SQL语句的执行过程
  • git笔记之重置本地仓库所有分支和远程保持一致、工作区恢复干净,像刚clone下来一样
  • 高级java每日一道面试题-2024年9月22日-数据库篇-char和varchar的区别是什么?
  • BERT训练之数据集处理(代码实现)
  • 展锐平台的手机camera 系统开发过程
  • Python项目的质量保证
  • C++——打印以下图案:用string方法。
  • 左值引用与右值引用
  • Tauri 应用 input 输入自动大写问题定位解决
  • 华为HarmonyOS灵活高效的消息推送服务(Push Kit) -- 9 撤回通知扩展消息
  • 【HTTP】请求“报头”(Host、Content-Length/Content-Type、User-Agent(简称 UA))
  • C# 免费离线人脸识别 2.0 Demo
  • Consul Config 使用Git做版本控制的实现
  • ES6 ...操作符
  • php的插入排序,通过双层for循环
  • 欢迎参加第二届中国游戏开发者大会
  • 区块链分支循环
  • 试着探索高并发下的系统架构面貌
  • 首页查询功能的一次实现过程
  • 腾讯优测优分享 | 你是否体验过Android手机插入耳机后仍外放的尴尬?
  • 听说你叫Java(二)–Servlet请求
  • 我与Jetbrains的这些年
  • 译有关态射的一切
  • 深度学习之轻量级神经网络在TWS蓝牙音频处理器上的部署
  • 函数计算新功能-----支持C#函数
  • ​Base64转换成图片,android studio build乱码,找不到okio.ByteString接腾讯人脸识别
  • ​一些不规范的GTID使用场景
  • # AI产品经理的自我修养:既懂用户,更懂技术!
  • #pragma data_seg 共享数据区(转)
  • #数据结构 笔记三
  • (1)Jupyter Notebook 下载及安装
  • (2)从源码角度聊聊Jetpack Navigator的工作流程
  • (Redis使用系列) SpringBoot中Redis的RedisConfig 二
  • (二)pulsar安装在独立的docker中,python测试
  • (二)WCF的Binding模型
  • (附源码)springboot“微印象”在线打印预约系统 毕业设计 061642
  • (附源码)SSM环卫人员管理平台 计算机毕设36412
  • (九)One-Wire总线-DS18B20
  • (六)vue-router+UI组件库
  • (六)什么是Vite——热更新时vite、webpack做了什么
  • (七)Java对象在Hibernate持久化层的状态
  • (五)大数据实战——使用模板虚拟机实现hadoop集群虚拟机克隆及网络相关配置
  • (转)IOS中获取各种文件的目录路径的方法
  • (转)memcache、redis缓存
  • (转)创业家杂志:UCWEB天使第一步
  • (转)负载均衡,回话保持,cookie
  • .net framework4与其client profile版本的区别
  • .NET MVC之AOP
  • .NET 命令行参数包含应用程序路径吗?
  • .NetCore 如何动态路由
  • .net企业级架构实战之7——Spring.net整合Asp.net mvc