首页 > 其他分享 >string和oj题以及vector的接口介绍

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

时间:2024-09-24 16:53:12浏览次数:3  
标签:begin capacity cout vector oj string size

前言

上篇博客学习了一些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;
}

在这里插入图片描述

标签:begin,capacity,cout,vector,oj,string,size
From: https://blog.csdn.net/2302_79180171/article/details/142456667

相关文章

  • String.intern()方法、==、equals()、运行时常量池
    尽管在输出中调用intern方法并没有什么效果,但是实际上后台这个方法会做一系列的动作和操作。在调用”ab”.intern()方法的时候会返回”ab”,但是这个方法会首先检查字符串池中是否有”ab”这个字符串,如果存在则返回这个字符串的引用,否则就将这个字符串添加到字符串池中,然会返回这个......
  • C++:STL:String类常用函数介绍(附加部分重要函数的模拟实现)
    C语言中,字符串是以'\0'结尾的一些字符的集合,为了操作方便,C标准库中提供了一些str系列的库函数,但是这些库函数与字符串是分离开的,不太符合OOP的思想,而且底层空间需要用户自己管理,稍不留神可能还会越界访问。如果我们经常在leetcode上刷OJ题,我们会发现字符串类型的题目基本都是......
  • Anaconda创建虚拟环境失败Malformed version string ‘~‘: invalid character(s)
     notepad%USERPROFILE%\.condarccondacreate-npy38python=3.8TRANSLATEwithxEnglishArabicHebrewPolishBulgarianHindiPortugueseCatalanHmongDawRomanianChineseSimplifiedHungarianRussianChineseTraditionalIndonesian......
  • 信息学奥赛复赛复习01-CSP-J2019-01-字符、字符数组、字符串、string、字符串读取
    信息学奥赛复赛复习01-CSP-J2019-01-字符、字符数组、字符串、string、字符串读取PDF文档公众号回复关键字:2024092312019CSP-J题目1数字游戏[题目描述]小K同学向小P同学发送了一个长度为8的01字符串来玩数字游戏,小P同学想要知道字符串中究竟有多少个1。注......
  • string的find()与npos
    在C++中,std::string::find()是一个用于在字符串中查找子字符串或字符的成员函数。查找成功时返回匹配的索引位置,查找失败时返回std::string::npos,表示未找到。std::string::find()函数原型std::size_tfind(conststd::string&str,std::size_tpos=0)constnoexcept;......
  • 什么情况下需要 new Date().toISOString()?,是否会受时区的影响吗?
    newDate().toISOString()是JavaScript中用于获取当前日期和时间的ISO8601格式字符串的方法。格式为YYYY-MM-DDTHH:MM:SS.sssZ。这种格式的字符串在很多场景中都非常有用,特别是在需要标准化日期和时间表示的情况下。以下是一些常见的使用场景:1.API通信在与后端API通......
  • `std::string_view`(c++17) 和 `std::stringstream` 使用区别·
    std::string_view和std::stringstream都是C++中处理字符串的工具,但它们的设计目标和使用场景非常不同。我们可以通过几方面进行对比。1.设计目的和核心功能std::string_view:设计用于只读访问字符串或字符序列。是一个轻量级的字符串视图,不会持有字符串的数据,仅仅是对......
  • C++ string
    在C++中,std::string类是处理字符串的主要工具。它提供了丰富的功能和方法来简化字符串操作,使得开发者可以更加方便地进行文本数据的处理。构造函数std::string类有多种构造函数供用户选择:使用C风格字符串初始化:string(constchar*s);使用指定字符重复初始化:string(size_......
  • [VLDBJ24] Survey of vector database management systems
    https://blog.csdn.net/Datawhale/article/details/1344535331.Intro非结构化数据压成\(D\)维向量五个问题:模糊搜索标准:向量不太适应模糊语义查询更多代价:\(O(D)\)内存消耗大:全要访问缺乏结构:(有结构的可以排序啥的index她不行)和属性不兼容(不太明白,可能是别的可以......
  • std::vector 和 std::map 都支持以下比较运算符
    在C++标准库中,std::vector和std::map都支持以下比较运算符:==(相等运算符)!=(不等运算符)<(小于运算符)<=(小于等于运算符)>(大于运算符)>=(大于等于运算符)1.std::vector的比较对于std::vector,这些运算符通过词典序比较(lexicographicalcomparison)进行。词典序比较类似于字......