【C++闯关笔记】STL:string的学习和使用(万字精讲)

​系列文章目录

第零篇:从C到C++入门:C++有而C语言没有的基础知识总结-CSDN博客

第一篇:【C++闯关笔记】封装①:类与对象-CSDN博客

第二篇:【C++闯关笔记】封装②:友元与模板-CSDN博客

第三篇:【C++闯关笔记】STL:string的学习和使用(万字精讲)-CSDN博客


目录

​系列文章目录

前言

一、什么是string类?

二、使用string:string类的常用函数

1.创建string对象

2.修改string对象

3.遍历string对象

 1)operator[ ]

2)迭代器遍历

3)范围for

4.string类对象容量相关函数

5.其他常用函数

1.查找字符或字符串:find和rfind

2.截取子字符串:substr

3.返回C格式字符串:c_str

4.获取一行字符:getline

三、模拟实现string

1.private成员

2.构造函数与析构函数

2.修改类函数

3.遍历类函数

4.其他常用函数

完整代码

总结



前言

什么是STL?

STL是C++标准库的重要组成部分,是一个可复用的组件库,它里面包罗有众多数据结构与算法。STL由六大组件构成:容器、算法、迭代器、函数对象、适配器、内存分配器这 6 部分构成,其中容器与算法最为重要,后面 4 部分都是为它两服务的。这些组件相互协作,共同实现了STL的强大功能。

为什么要学习STL?

STL是C++中的优秀作品代表,如果能够熟练的使用STL乃至了解底层原理,那么许多底层的数据结构以及算法都不需要自己重新编码,可以直接复用前人的优秀成果,相当于站在巨人的肩膀上,大幅提升开发速度。

本系列将从STL的各个容器与算法着手,先详细介绍它们使用方法然后通过自实现的方式理解它们的底层逻辑。

本文主要介绍string的学习与使用。


一、什么是string类?

在C语言中,字符串是char[ ]数组以'\0'结尾的一些字符的集合,C标准库有一些str系列的库函数专门用以操作这些字符串。 但是这些库函数与字符串是分离开的,不太符合C++面对对象的思想。

于是在C++中将原C语言中的字符串与相关函数并结合数据结构顺序表,将它们整合打造成为一个类——用以专门表示字符串的字符串类即string类,以便使用。

对于刚接触string的新人而言,可以将string先理解为一种特化的顺序表——专门为存储和操作字符数据而设计。结合数据结构顺序表的原理,先在脑海中有个大致的模型,之后在学习string相关接口时更加游刃有余。

string类与C语言的数组有什么区别?

①char s[ ]本质上还是数组,长度固定;string长度不限

②string本质是类,其中包含有大量函数,方便操作;

③string中重载了如‘+’ ’>' '<"等符号,便于操作;

可以将string理解为包含了大量函数的char s[ ]。


二、使用string:string类的常用函数

在使用string类时,必须包含#include<string>头文件以及using namespace std;

1.创建string对象

在日常编码中,我们常用到的四种方法创建string对象。

string类对象的常见构造函数

构造函数功能说明
string()构造空的string类对象,即空字符串
string(const char* s)用C语言的字符串来构造string类对象
string(size_t n, char c)创建的string类对象中包含n个字符c
string(const string&s)拷贝构造函数,将已有的对象拷贝给一个新的对象

示例

	string s1;string s2("hello String");string s3(7, 'a');string s4(s3);

解释:string s3(7,‘a'),这里将’a‘字符复制了7遍后存入字符串对象s3.

string的构造函数除了上述最常用的四种外还包括:

2.修改string对象

string类对象的常见修改函数

①增加类型函数

函数名称功能说明
push_back('c')在字符串后尾插字符c
appden(“字符串” )在字符串末尾追加一个字符串
operator+=将两个字符串合并

示例

int main()
{string s1("he");string s2("String");s1.push_back('l');s1.append("lo ");s1 += s2;cout << s1 << endl;//打印结果为“hello String”return 0;
}

②减删类型函数

函数名称功能说明
pop_back( )删除字符串末尾字符

erase(size_t pos,size_t n);

erase(size_t pos)

从索引pos位置开始,往后删除n个字符(包括pos);

将pos位置及以后的字符删除。

clear( )清空整个字符串

示例

int main()
{string s1("hello string");s1.pop_back();s1.erase(7, 4);s1.erase(5);s1.clear();return 0;
}

细节注意:

1.确保你的删除位置pos在 [0,size()] 范围内。

2.调用 pop_back() 之前,最好检查一下检查一下字符串是否为空 !str.empty( );

3.遍历string对象

string对象常用的遍历方法包括三种:

函数名称功能说明
operator[pos ]返回pos位置的字符

begin+end;

rbegin+rend;

迭代器遍历

for(auto:str)范围for

 1)operator[ ]

string重载了[ ],可以通过下标访问。

使用示例

2)迭代器遍历

这里的迭代器可以理解为封装过后的“指针”;

(1)正着遍历:begin+end

使用语法

string::iterator 变量名 = 对象.begin( );(end同理)

string::iterator it = s.begin();//iterator为关键字,it为变量名

使用示例

(2)反向遍历:rbegin+rend

使用语法

string::reverse_iterator 变量名 = 对象.rbegin( );(rend同理)

string::reverse_iterator rit = s.rbegin();//reverse_iterator为关键字

使用示例

3)范围for

语法

for(auto 变量名 : 对象)

auto,自动推测变量类型,中间由‘ :’隔开

(这里简述auto与范围for,主要目的是能介绍这种遍历方法,有兴趣的读者可参看:)从C到C++入门:C++有而C语言没有的基础知识总结-CSDN博客

范围for的底层是由迭代器实现的。

使用示例

4.string类对象容量相关函数

函数名功能
size( )返回字符串有效字符长度
length( )返回字符串有效字符长度
capacity( )返回该对象占用空间大小
empty()检测该string对象是否为空,是返回true,否则返回false
reserve(size_t n)将字符串空间拓展为n
resize(size_t n,char c)将有效字符的个数改成成n个,多出的空间用字符c填充

说明:

①size()与length()方法底层实现原理完全相同,引入size()的原因是为了与其他容器的接口保持一 致,一般情况下基本都是用size();

②resize与reserve的核心区别

  • resize(n,c):改变字符串的“逻辑长度” (即size())。 它会直接让你看到的字符串内容变长或变短。当 n 比目前字符串长度长时,多出空间用字符c填充;当 n 比目前字符串长度短时,会截取字符串长度至n。

  • reserve(n):改变字符串的“总容量” (即capacity())。 它只是为你将来要放入的字符预先申请一大块内存(可能不会严格申请至 n 空间),但不会改变你当前看到的字符串内容。

使用示例

int main()
{string s("hello");cout <<s <<' ' << s.size() << ' ' << s.capacity() << endl;s.reserve(64);//将总空间大小拓展为64,多出的部分为空白;s.resize(32, 'a');//将实际使用空间拓展至32,多出部分填字符'a';cout << s << ' ' << s.size() << ' ' << s.capacity() << endl;return 0;
}

陷阱注意

①reserve() 不会初始化内存

reserve()只会申请空间,不会将申请出来的空间赋值。如果通过 [] 操作符访问 [size(), capacity()) 范围内的内存是未定义行为

reserve() 只增不减

reserve(n) 是将容量拓展至 至少是 n。如果你传入一个比当前 capacity() 还小的值,是不会实现的。

resize(n)   如果未指定初始化字符,则新添加的字符会被默认初始化为空字符 '\0'。

5.其他常用函数

1.查找字符或字符串:find和rfind

作用:在字符串中寻找带查找字符或字符串出现的位置,找到则返回其首下标,没有则返回-1。

使用方法:

s.find("你要找到字串",pos);pos,指从该位置往后找,若没有输入pos则默认从头开始找。

s.rfind("你要找到字串",pos);pos是指从该位置往前找,若没有输入pos则默认从头开始找。

示例:

注意:若没有输入pos,则find默认从首字符开始找;rfind从尾字符开始找。

2.截取子字符串:substr

作用:截取子字符串,当长度超过原字符串时,截取已有剩余的全部字符。

使用方法:

s.substr(pos,len);len是你要截取的长度,若不给len,则默认从pos位置取完剩下的。

示例:

3.返回C格式字符串:c_str

为了保持与C语言的兼容性,c_str函数便孕育而出了。

作用:返回一个指向当前字符串内容的、以空字符 '\0' 结尾的 C风格字符串(即 const char*)。

使用方法:

const char *s =对象.c_str();

示例:

4.获取一行字符:getline

在平常通过 cin 输入字符串时,如果遇到空格就会停止输入,如

int main()
{string s;//输入“hello world”;cin >> s;//只打印出“hello”cout << s << endl;return 0;
}

getline函数的作用就是将一整行输入都存入字符串。

使用方法:

getline(cin,string对象);//注意getline并非string类的成员函数!

示例


三、模拟实现string

1.private成员

类似于数据结构顺序表:

char* _s用于存储字符串;

size_t _capacity表示在堆上申请的空间数量;

size_t _size表示实际使用了多少空间。

size_t 可以看成没有负数的int型。

namespace karsen
{class string{private:size_t _size;size_t _capacity;char* _s;};
}

2.构造函数与析构函数

两种构造函数以实现:①空对象;②括号内赋初值;③创建的string类对象中包含n个字符c。

以及拷贝构造函数,析构函数。

注意:

①new 与 delete,new[ ]与delete[ ]配合使用,否则无法正确释放空间。

②必须实现拷贝构造函数,因为默认拷贝构造是按字节拷贝的“浅拷贝”,他会将原对象的数据原模原样的拷贝进新对象,当析构函数释放空间时就会造成释放两次导致报错。

namespace karsen
{class string{public://传入字符串构建string(const char* s = nullptr){//空对象给它两个空间if (!s || s[0] == '\0'){_s = new char[2];_s[0] = '\0';_size = 0;_capacity = 2;return;}_size = strlen(s);_capacity = _size + 1;_s = new char[_size + 1];strcpy(_s, s);}//创建的string类对象中包含n个字符cstring(int n, char c){if (n > 0){_size = n;_s = new char[_size + 1];for (int i = 0; i < n; ++i)_s[i] = c;_s[_size] = '\0';}}string(const string& s){_size = s._size;_capacity = s._capacity + 1;_s = new char[_capacity];strcpy(_s, s._s);}~string(){delete[] _s;_size = _capacity = 0;_s = nullptr;}private:size_t _size;size_t _capacity;char* _s;};

2.修改类函数

注意在push_back中,当_size==_capacity-1时就要扩容,因为push之后需要设置_s[_size] = '\0';防止越界。

erase函数使用了函数重载,以满足在不传入参数二时的删除工作。

    	void push_back(char c){if (_size == _capacity-1){size_t newcapa = _capacity * 2;reserve(newcapa);}_s[_size++] = c;_s[_size] = '\0';}void reserve(size_t n){if (n > _capacity){_capacity = n;char* news = new char[_capacity];strcpy(news, _s);delete[] _s;_s = news;}}void pop_back(){if (_size > 0){_size--;}}void append(const char* s){if (s){size_t len = strlen(s);size_t newsize = len + _size;if (newsize > _capacity){reserve(newsize);}strcpy(_s + _size, s);_size += len;//_s[_size] = '\0';//+=那可能用到}}string& operator+=(const char* s){append(s);return *this;}string& operator+=(const char s){push_back(s);return *this;}void erase(size_t pos){_size = pos;_s[_size] = '\0';}void erase(size_t pos, int n){if (n > 0){size_t end = pos + n;if (end < _size){while (end < _size){_s[pos++] = _s[end++];}_size = pos;_s[_size] = '\0';}else{erase(pos);}}else return;}void clear(){_size = 0;_s[_size] = '\0';}

3.遍历类函数

注意:范围for底层调用的是迭代器。

		char& operator[](size_t n){if (n < _size){return _s[n];}else{//越界抛异常throw std::out_of_range("Index out of range");}}//用于const型对象const char& operator[](int& n)const{if (n < _size){return _s[n];}else{//越界抛异常throw std::out_of_range("Index out of range");}}typedef char* iterator;//迭代器iterator begin(){return _s;}iterator end(){return _s + _size;}

4.其他常用函数

解释:

①resize分两大类:n是否大于capacity。在n小于capacity一类中又可分为:n是否大于size。

②通过重载find,以达到查找单个字符与字符串的目的。在第二个find函数中,利用指针变量本质存储的是地址数据且每个地址空间正好等于char大小,将前后地址相减取得间距。

③在substr函数的第一个if中,如果len的值没变还是-1,或者pos+len的大小超过实际对象中存储字符串的大小,那么将pos之后的字符串(_s+pos)传递给一个临时变量返回。

如果不满足第一个if,那么po与len之间一定在已有的数据中,将这些数据push进临时变量再返回。

注意:不要返回临时变量的引用。

		size_t size(){return _size;}size_t capacity(){return _capacity;}bool empty(){if (_size > 0)return true;else return false;}void resize(size_t n, char c){if (n > _capacity){reserve(n);}if (n > _size){while (_size < n){_s[_size++] = c;}}else{_size = n;_s[_size] = '\0';}}int find(const char a,int pos = 0){if (pos < 0 || pos > _size)return -1;for (int i = pos; i < _size; ++i){if (_s[i] == a)return i;}return -1;}int find(const char* a, int pos = 0){if (pos < 0 || pos > _size)return -1;const char* temp = strstr(_s + pos, a);if (!temp)return -1;else return (int)(temp - _s);}//会传下标int rfind(const char a, int pos){if (pos < 0 || pos > _size){return -1;}for (int i = pos; i > -1 ; --i){if (_s[i] == a)return i;}return -1;}//不会传下标int rfind(const char a, size_t pos = 1){pos = _size;for (size_t i = pos; i > -1; --i){if (_s[i] == a)return (int)i;}return -1;}const char* c_str(){return _s;}string substr(int pos, int len = -1){if (pos<0 || pos>_size)return nullptr;if (len == -1 || pos + len >=_size){string ret(_s + pos);return ret;}else{string ret;for (int i = pos; i < pos + len; ++i){if (i < _size)ret.push_back(_s[i]);else break;}return ret; }}//重载输入输出符std::ostream& operator<<(std::ostream& out, const string& s){out << s._s;return out;}std::istream& operator>>(std::istream& in, string& s){s.clear(); char c;while (in.get(c)){if (c == '\n' || c ==' ')break;s.push_back(c);}//在push_back中已经处理过了,这里就不用,也不能(越界)//s[s._size] = '\0';return in;}

完整代码

如果不需要namespace,可以直接将其中的代码复制到外部。

//#define  _CRT_SECURE_NO_WARNINGS//这个宏用于去除vs编译器的不安全提醒
#pragma once
#include<iostream>namespace karsen
{typedef char* iterator;typedef char* reverse_iterator;class string{friend std::ostream& operator<<(std::ostream& out, const string& s);friend std::istream& operator>>(std::istream& in,string& s);public://传入字符串构建string(const char* s = nullptr){if (!s || s[0] == '\0'){_s = new char[2];_s[0] = '\0';_size = 0;_capacity = 2;return;}_size = strlen(s);_capacity = _size + 1;_s = new char[_size + 1];strcpy(_s, s);}//创建的string类对象中包含n个字符cstring(int n, char c){if (n > 0){_size = n;_s = new char[_size + 1];for (int i = 0; i < n; ++i)_s[i] = c;_s[_size] = '\0';}}string(const string& s){_size = s._size;_capacity = s._capacity + 1;_s = new char[_capacity];strcpy(_s, s._s);}void push_back(char c){if (_size == _capacity-1){size_t newcapa = _capacity * 2;reserve(newcapa);}_s[_size++] = c;_s[_size] = '\0';}void pop_back(){if (_size > 0){_size--;}}size_t size(){return _size;}size_t capacity(){return _capacity;}void append(const char* s){if (s){size_t len = strlen(s);size_t newsize = len + _size;if (newsize > _capacity){reserve(newsize);}strcpy(_s + _size, s);_size += len;//_s[_size] = '\0';//+=那可能用到}}string& operator+=(const char* s){append(s);return *this;}string& operator+=(const char s){push_back(s);return *this;}char& operator[](size_t n){if (n < _size){return _s[n];}else{//越界抛异常throw std::out_of_range("Index out of range");}}const char& operator[](int& n)const{if (n < _size){return _s[n];}else{//越界抛异常throw std::out_of_range("Index out of range");}}void erase(size_t pos){_size = pos;_s[_size] = '\0';}void erase(size_t pos, int n){if (n > 0){size_t end = pos + n;if (end < _size){while (end < _size){_s[pos++] = _s[end++];}_size = pos;_s[_size] = '\0';}else{erase(pos);}}else return;}void reserve(size_t n){if (n > _capacity){_capacity = n;char* news = new char[_capacity];strcpy(news, _s);delete[] _s;_s = news;}}void clear(){_size = 0;_s[_size] = '\0';}//迭代器iterator begin(){return _s;}iterator end(){return _s + _size;}//方向迭代需要重载++变--//reverse_iterator rend()//{//	return _s;//}//reverse_iterator rbegin()//{//	return _s + _size-1;//}bool empty(){if (_size > 0)return true;else return false;}void resize(size_t n, char c){if (n > _capacity){reserve(n);}if (n > _size){while (_size < n){_s[_size++] = c;}}else{_size = n;_s[_size] = '\0';}}int find(const char a,int pos = 0){if (pos < 0 || pos > _size)return -1;for (int i = pos; i < _size; ++i){if (_s[i] == a)return i;}return -1;}int find(const char* a, int pos = 0){if (pos < 0 || pos > _size)return -1;const char* temp = strstr(_s + pos, a);if (!temp)return -1;else return (int)(temp - _s);}//会传下标int rfind(const char a, int pos){if (pos < 0 || pos > _size){return -1;}for (int i = pos; i > -1 ; --i){if (_s[i] == a)return i;}return -1;}//不会传下标int rfind(const char a, size_t pos = 1){pos = _size;for (size_t i = pos; i > -1; --i){if (_s[i] == a)return (int)i;}return -1;}const char* c_str(){return _s;}string substr(int pos, int len = -1){if (pos<0 || pos>_size)return nullptr;if (len == -1 || pos + len >=_size){string ret(_s + pos);return ret;}else{string ret;for (int i = pos; i < pos + len; ++i){if (i < _size)ret.push_back(_s[i]);else break;}return ret; }}~string(){delete[] _s;_size = _capacity = 0;_s = nullptr;}public://以下作为组件函数使用private:size_t _size;size_t _capacity;char* _s;};std::ostream& operator<<(std::ostream& out, const string& s){out << s._s;return out;}std::istream& operator>>(std::istream& in, string& s){s.clear(); char c;while (in.get(c)){if (c == '\n' || c ==' ')break;s.push_back(c);}//在push_back中已经处理过了,这里就不用,也不能(越界)//s[s._size] = '\0';return in;}}


总结

本文先详细介绍了什么是STL以及string是什么,然后再介绍了string的一些常用函数的使用方法,最后通过模拟实现string以求深入理解string。

整理不易,希望能帮到你。

读完点赞,手留余香~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/pingmian/94252.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/94252.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

06 - spring security角色和权限设置

spring security角色和权限设置 文档 00 - spring security框架使用01 - spring security自定义登录页面02 - spring security基于配置文件及内存的账号密码03 - spring security自定义登出页面04 - spring security关闭csrf攻击防御05 - spring security权限控制 角色和权限…

如何实现文档处理全流程自动化?

在处理文本文档、电子邮件、视频音频、社媒帖子等非结构化数据时&#xff0c;我们经常发现这些数据难以用传统的数据库表格进行存储和管理&#xff0c;因为其没有明确的结构和标准化的格式&#xff0c;因此&#xff0c;这类数据处理难度较大&#xff0c;当传统“人眼Excel”模式…

Java Main无法初始化主类的原因与解决方法(VsCode工具)

个人操作 由于上传git将target目录也上传了所以在本地删除target之后再重新同步更新动作然后直接在vscode工具上run本地项目运行报错&#xff0c;报错信息如下 报错信息分析原因1. 工具配置 用 VS Code 的“Run”运行按钮时&#xff0c;是否会自动编译&#xff0c;取决于你的 V…

Azure Kubernetes Service (AKS)

Overview AKS&#xff08;Azure Kubernetes Service&#xff09; 是 Microsoft Azure 提供的一种托管Kubernetes 服务&#xff0c;旨在简化 Kubernetes 集群的部署、管理和操作。轻松运行和扩展基于容器的应用程序&#xff0c;而无需管理 Kubernetes 本身的基础设施。 AKS与 …

基于SpringBoot的校园信息共享系统【2026最新】

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏&#xff1a;…

PyTorch API 3 - distributed

文章目录分布式通信包 - torch.distributed后端支持PyTorch 内置的后端选择哪个后端&#xff1f;常见环境变量选择使用的网络接口其他NCCL环境变量基础概念初始化返回类型&#xff1a;boolTCP初始化共享文件系统初始化环境变量初始化方法初始化后操作关闭处理重新初始化组Devic…

【K8s】整体认识K8s之Docker篇

首先认识几个名词&#xff0c;Docker-ce是docker的社区版本&#xff0c;提供给各种构建、发布、运行容器的工具&#xff1b;docker-ce-cli是社区版本的命令行工具&#xff0c;与docker守护进程进行交互&#xff1b;containerd.io是docker运行时&#xff08;containerd&#xff…

【机器学习】7 Linear regression

本章目录 7 Linear regression 217 7.1 Introduction 217 7.2 Model specification 217 7.3 Maximum likelihood estimation (least squares) 217 7.3.1 Derivation of the MLE 219 7.3.2 Geometric interpretation 220 7.3.3 Convexity 221 7.4 Robust linear regression * 2…

【卫星通信】超低码率语音编码ULBC:EnCodec神经音频编解码器架构深度解析

引言 EnCodec是由Meta AI提出的一种端到端神经音频编解码器架构&#xff0c;其核心目标是在保证音频质量的前提下实现高压缩比和低带宽传输。该模型通过结合卷积神经网络、残差矢量量化&#xff08;Residual Vector Quantization, RVQ&#xff09;、多尺度对抗训练以及Transfor…

08_正则表达式

第8课:正则表达式 课程目标 理解正则表达式的基本概念 掌握常用的正则表达式模式 学习Python中re模块的使用 能够编写简单的正则表达式 1. 正则表达式基础 1.1 什么是正则表达式 正则表达式是一种用于匹配字符串模式的工具,可以用于搜索、替换和验证文本。 1.2 基本语法 …

小迪安全v2023学习笔记(七十一讲)—— Python安全反序列化反编译格式化字符串安全

文章目录前记WEB攻防——第七十一天Python安全&反序列化利用链&PYC文件反编译&格式化字符串安全Python - PYC-反编译文件出源码介绍演示Python - 反序列化-调用链&魔术方法各类语言序列化和反序列化函数序列化和反序列化含义Python中常用的序列化/反序列化函数…

Linux->多线程2

目录 本文说明&#xff1a; 一&#xff1a;线程互斥 1&#xff1a;缺乏互斥的抢票系统 2&#xff1a;抢票系统分析及概念回顾 3&#xff1a;互斥锁 ①&#xff1a;相关接口 a&#xff1a;定义锁 b&#xff1a;初始化锁 c&#xff1a;加锁 d&#xff1a;解锁 e&#x…

[OpenVela] 音乐播放器1.0

code: https://github.com/lvy010/vela/tree/main/music_player OpenVela 音乐播放器 基于 OpenVela 系统的嵌入式音乐播放器&#xff0c;使用 LVGL 图形库开发&#xff0c;支持 Wi-Fi 连接和本地音频播放。 &#x1f4cb; 目录 项目简介功能特性系统要求项目结构快速开始配…

学习 Android (十六) 学习 OpenCV (一)

学习 Android (十六) 学习 OpenCV (一) 在前几个章节中&#xff0c;我们对 NDK 相关的开发有了一定的了解&#xff0c;所谓磨刀不误砍柴工&#xff0c;有了这些基础的知识储备之后&#xff0c;我们可以来简单上手一下 OpenCV 相关的知识&#xff0c;接下来跟随作者一起来学习吧…

人工智能之数学基础:离散型随机变量

本文重点 前面我们介绍了随机变量具有两个类型,一个类型是离散型随机变量,另外一个类型是连续型随机变量。我们先来学习离散型随机变量。 离散型随机变量 离散型随机变量 X 所有可能取的值为X1,X2...,并且有: 则称 p1 , p2, … 为离散型随机变量 X 的概率质量函数。其中 …

【Java开发日记】我们来讲一讲 Channel 和 FileChannel

目录 Channel FileChannel 打开 FileChannel 从 FileChannel 读数据 写数据到 FileChannel 关闭 FileChannel 示例 读数据 写数据 Channel 在 NIO 中&#xff0c;Channel 和 Buffer 是相辅相成的&#xff0c;只能从 Channel 读取数据到 Buffer 中&#xff0c;或者从 …

【力扣】2623. 记忆函数——函数转换

【力扣】2623. 记忆函数——函数转换 文章目录【力扣】2623. 记忆函数——函数转换一、题目二、解决方案1、概述1.1纯函数2、在Web开发中的记忆化用途2.1缓存网站文件&#xff08;1&#xff09;React 组件&#xff08;2&#xff09;缓存 API 调用3、算法中的记忆化4、专业实现的…

数据结构 -- 队列

队列的核心定义队列是受限线性表&#xff0c;仅允许在一端&#xff08;队尾&#xff09;插入元素、另一端&#xff08;队头&#xff09;删除元素&#xff0c;遵循 “先进先出&#xff08;FIFO&#xff0c;First In First Out&#xff09;” 原则。队列的结构与操作端队尾&#…

为什么hive在处理数据时,有的累加是半累加数据

在 Hive 处理数据时&#xff0c;“半累加数据” 指的是部分字段保留历史状态、部分字段随业务变化累加或更新的场景&#xff0c;这种模式广泛存在于需要兼顾 “历史追溯” 和 “增量更新” 的业务中。以下是具体例子&#xff0c;帮助理解其本质&#xff1a;例子 1&#xff1a;用…

【贪心算法】day2

&#x1f4dd;前言说明&#xff1a; 本专栏主要记录本人的贪心算法学习以及LeetCode刷题记录&#xff0c;按专题划分每题主要记录&#xff1a;&#xff08;1&#xff09;本人解法 本人屎山代码&#xff1b;&#xff08;2&#xff09;优质解法 优质代码&#xff1b;&#xff…