Python 之 Pandas Series 数据结构

news2024/9/24 1:14:21

文章目录

  • 一、Series 结构
  • 二、数据结构 Series 创建
    • 1. 创建
      • 1.1 列表/数组作为数据源创建 Series
      • 1.2 字典作为数据源创建 Series
      • 1.3 通过标量创建
    • 2. 参数说明
      • 2.1 index 参数
      • 2.2 name 参数
      • 2.3 copy 参数
  • 三、Series 的索引/切片
    • 1. 下标索引
    • 2. 标签索引
    • 3. 切片
  • 四、Series 数据结构的基本技巧
    • 1. 查看前几条和后几条数据
    • 2. 重新索引:reindex
    • 3. 对齐运算
    • 4. 删除和添加

一、Series 结构

  • Series 结构,也称 Series 序列,是 Pandas 常用的数据结构之一,它是一种类似于一维数组的结构,由一组数据值(value)和一组标签组成,其中标签与数据值具有对应关系。
  • 标签不必是唯一的,但必须是可哈希类型(也就是不可变类型,就像整型、字符串型等)。该对象既支持基于整数的索引,也支持基于标签的索引,并提供了许多方法来执行涉及索引的操作。ndarray 的统计方法已被覆盖,以自动排除缺失的数据(目前表示为 NaN)。
  • Series 可以保存任何数据类型,比如整数、字符串、浮点数、Python 对象等,它的标签默认为整数,从 0 开始依次递增。
  • Series 的结构图,如下所示:

在这里插入图片描述

  • 通过标签我们可以更加直观地查看数据所在的索引位置。
  • 在这里,我们引入 numpy 和 pandas 库,便于后续的操作。
import numpy as np
import pandas as pd

二、数据结构 Series 创建

  • Series 的语法模板如下:
pd.Series(data=None, index=None, dtype=None, name=None, copy=False)
  • 其参数含义如下:
  • data 表示输入的数据,可以是列表、常量、ndarray 数组等,如果是字典,则保持参数顺序。
  • index 表示索引值,必须是可散列的(也就是不可变数据类型,就像 str,bytes 和数值类型),并且与数据具有相同的长度,允许使用非唯一索引值。如果未提供,将默认为 RangeIndex(0,1,2,…,n)。
  • dtype 表示输出系列的数据类型。如果未指定,将从数据中推断数据类型。
  • name 是给 Series 定义一个名称。
  • copy 表示对 data 进行拷贝,默认为 False,仅影响 Series 和 ndarray 数组。

1. 创建

1.1 列表/数组作为数据源创建 Series

  • (1) 以列表作为数据创建 Series。
ar_list = [3,10,3,4,5]
print(type(ar_list))
s1 = pd.Series(ar_list)
print(s1)
print(type(s1))
#<class 'list'>
#0     3
#1    10
#2     3
#3     4
#4     5
#dtype: int64
#<class 'pandas.core.series.Series'>
  • (2) 以数组作为数据创建 Series。
np_rand = np.arange(1,6)
s1 = pd.Series(np_rand)
s1
#0    1
#1    2
#2    3
#3    4
#4    5
#dtype: int32
  • (3) 通过 index 和 values 属性取得对应的标签和值。
  • 我们可以取出 Series 当中的所有标签值,默认为 RangeIndex(0,1,2,…,n)。
s1.index
#RangeIndex(start=0, stop=5, step=1)
  • 当然,我们可以强制转化为列表输出。
list(s1.index)
#[0, 1, 2, 3, 4]
  • 我们也取出 Series 的所有数据值,他们的数据类型为 ndarray。
print(s1.values, type(s1.values))
#[1 2 3 4 5] <class 'numpy.ndarray'>
  • (4) 通过标签取得对应的值,或者修改对应的值。
  • 我们可以输出 s1 当中索引为 1 的数据。
s1[1] 
#2
  • 我们也可以修改 s1 当中索引为 2 的数据。
s1[2] = 50 
s1
#0     1
#1     2
#2    50
#3     4
#4     5
#dtype: int32
  • 如果我们直接以负数作为索引值对 s1 进行操作,会直接报错,但可以通过新增索引和数据值进行操作。
  • (5) 和列表索引区别。
  • (a) 默认的索引 RangeIndex,不能使用负值,来表示从后往前找元素。
s1[-1] = 20
s1
# 0     1
# 1     2
# 2    50
# 3     4
# 4     5
#-1    20
#dtype: int64
  • (b) 获取不存在的索引值对应数据,会报错,但是可以赋值,相当于新增数据。
s1[-1] = 20
print(s1)
print(s1.index)
# 0     1
# 1     2
# 2    50
# 3     4
# 4     5
#-1    20
#dtype: int64
#Int64Index([0, 1, 2, 3, 4, -1], dtype='int64')
  • (c) 可以新增不同类型索引的数据,新增不同类型索引的数据,索引的类型会发生自动变化。
s1["a"] = 40
s1.index
#Index([0, 1, 2, 3, 4, -1, 'a'], dtype='object')

1.2 字典作为数据源创建 Series

  • (1) 以字典作为数据创建 Series。
d = {'a': 1, 'b': 2, 'c': 3}
ser = pd.Series(data=d)
ser
#a    1
#b    2
#c    3
#dtype: int64
  • (2) 通过 index 和 values 属性取得对应的标签和值。
  • 具体可见如下例子。
ser.index
ser.values
#Index(['a', 'b', 'c'], dtype='object')
#array([1, 2, 3], dtype=int64)
  • (3) 通过标签取得对应的值,或者修改对应的值。
  • 和使用列表、数组创建 Series 一样,我们可以通过调用标签得到对应的数据。
ser['a']
#1
  • 通过标签修改对应的数据。
ser["s"] = 50
#a     1
#b     2
#c     3
#s    50
#dtype: int64
  • 如果标签非数值型,我们既可以用标签获取值,也可以用标签的下标获取值。
ser[0]
#1
  • 负数表示从后往前进行索引。
ser[-1]
#50
  • 也可以直接全部进行修改。
d = {'a': 1, 5: 2, 'c': 3}
ser1 = pd.Series(data=d)
ser1
#a    1
#5    2
#c    3
#dtype: int64
  • 那么,当标签存在数值型的数据,就不可以使用标签的下标获取值,不然会直接报错。
  • (4) 取得数据时,先进行标签的检查,如果标签中没有,再进行索引的检查,都不存在则报错。

1.3 通过标量创建

s = pd.Series(100,index=range(5))
s
#0    100
#1    100
#2    100
#3    100
#4    100
#dtype: int64

2. 参数说明

2.1 index 参数

  • 索引值,必须是可散列的(不可变数据类型,例如 str,bytes 和数值类型),并且与数据具有相同的长度,允许使用非唯一索引值。如果未提供,将默认为 RangeIndex(0,1,2,…,n)。
  • (1) 使用显式索引的方法定义索引标签。
  • 当我们自定义索引标签(即显示索引)时,需要和数据长度一致。
data = np.array(['a','b','c','d'])
s = pd.Series(data,index=[100,101,102,103])
s
#100    a
#101    b
#102    c
#103    d
#dtype: object

(2) 从指定索引的字典构造序列。

d = {'a': 1, 'b': 2, 'c': 3}
ser = pd.Series(d, index=['a', 'b', 'c'])
ser
#a    1
#b    2
#c    3
#dtype: int64
  • (3) 当传递的索引值未匹配对应的字典键时,使用 NaN(非数字)填充。
d = {'a': 1, 'b': 2, 'c': 3}
ser = pd.Series(data=d, index=['x', 'b', 'z'])
ser
#x    NaN
#b    2.0
#z    NaN
#dtype: float64
  • 这里需要注意的是,索引是首先使用字典中的键构建的。在此之后,用给定的索引值对序列重新编制索引,因此我们得到所有 NaN。
  • (4) 通过匹配的索引值,改变创建 Series 数据的顺序。
d = {'a': 1, 'b': 2, 'c': 3}
ser = pd.Series(data=d, index=['c', 'b', 'a'])
ser
#c    3
#b    2
#a    1
#dtype: int64

2.2 name 参数

  • 我们可以给一个 Series 对象命名,也可以给一个 Series 数组中的索引列起一个名字,pandas 为我们设计好了对象的属性,并在设置了 name 属性值用来进行名字的设定。以下程序可以用来完成该操作。
dict_data1 = {
    "Beijing":2200,
    "Shanghai":2500,
    "Shenzhen":1700
}
data1 = pd.Series(dict_data1)
data1.name = "City_Data"
data1.index.name = "City_Name"
data1
#City_Name
#Beijing     2200
#Shanghai    2500
#Shenzhen    1700
#Name: City_Data, dtype: int64
  • 序列的名称,如果是 DataFrame 的一部分,还包括列名。
  • 如果用于形成数据帧,序列的名称将成为其索引或列名。每当使用解释器显示序列时,也会使用它。

2.3 copy 参数

  • copy 表示对 data 进行拷贝,默认为 False,仅影响 Series 和 ndarray 数组。
  • 我们以数组作为数据源,使用数组创建 Series。
np_rand = np.arange(1,6)
s1 = pd.Series(np_rand)
s1
#0    1
#1    2
#2    3
#3    4
#4    5
#dtype: int32
  • 然后,我们改变 Series 标签为 1 的值,并在输出 Series 的对象 s1 的同时,输出数组对象 np_rand。
s1[1] = 50
print("s1:",s1)
print("np_rand:",np_rand)
#s1: 0     1
#1    50
#2     3
#3     4
#4     5
#dtype: int32
#np_rand: [ 1 50  3  4  5]
  • 当源数据不是 Series 和 ndarray 类型时,我们以列表作为数据源,使用列表创建 Series。
my_list = [1,2,3,4,5,6]
s2 = pd.Series(my_list)
s2
#0    1
#1    2
#2    3
#3    4
#4    5
#5    6
#dtype: int64
  • 然后,我们改变 Series 标签为 1 的值,并在输出 Series 的对象 s2 的同时,输出数组对象 my_list。
s2[1] = 50print("s2:",s2)print("my_list:",my_list)
#s2: 0     1
#1    50
#2     3
#3     4
#4     5
#5     6
#dtype: int64
#my_list: [1, 2, 3, 4, 5, 6]

三、Series 的索引/切片

1. 下标索引

  • 下标索引类似于列表索引。
s = pd.Series(np.random.rand(5))
print(s)
print(s[3], type(s[3]), s[3].dtype)
#0    0.777657
#1    0.622071
#2    0.348129
#3    0.756216
#4    0.287849
#dtype: float64
#0.7562162366628223 <class 'numpy.float64'> float64
  • 上面的位置索引和标签索引刚好一致,会使用标签索引。
  • 当使用负值时,实际并不存在负数的标签索引。

2. 标签索引

  • 当索引为 object 类型时,既可以使用标签索引也可以使用位置索引。
  • Series 类似于固定大小的 dict,把 index 中的索引标签当做 key,而把 Series 序列中的元素值当做 value,然后通过 index 索引标签来访问或者修改元素值。
  • 使用索标签访问单个元素值。
s = pd.Series(np.random.rand(5),index=list("abcde"))
print(s["b"], type(s["b"]), s["b"].dtype)
#0.26319645172526607 <class 'numpy.float64'> float64
  • 使用索引标签访问多个元素值,注意需要选择多个标签的值,用 [[]] 来表示(相当于 [] 中包含一个列表)。
s = pd.Series([6,7,8,9,10],index = ['a','b','c','d','e'])
print(s)
print(s[['a','c','d']])
#a     6
#b     7
#c     8
#d     9
#e    10
#dtype: int64
#a    6
#c    8
#d    9
#dtype: int64
  • 多标签会创建一个新的数组。
s1 = s[["b","a","e"]]
s1["b"] = 10
print("s1:",s1)
print("s源数据:",s)
#s1: b    10
#a     6
#e    10
#dtype: int64
#s源数据: a     6
#b     7
#c     8
#d     9
#e    10
#dtype: int64

3. 切片

  • Series 使用标签切片运算与普通的 Python 切片运算不同,Series 使用标签切片时,其末端是包含的。
  • Series 使用 python 切片运算即使用位置数值切片,其末端是不包含。
  • 通过下标切片的方式访问 Series 序列中的数据,示例如下:
s = pd.Series(np.random.rand(10))
s
#0    0.927452
#1    0.235768
#2    0.516178
#3    0.277643
#4    0.697771
#5    0.273533
#6    0.133503
#7    0.185826
#8    0.687192
#9    0.316528
#dtype: float64
  • 位置索引和标签索引刚好一致,使用切片时,如果是数值会认为是 python 切片运算,不包含末端。
s = pd.Series([1,2,3,4,5],index = ['a','b','c','d','e'])
print(s)
print(s[1:4])
#a    1
#b    2
#c    3
#d    4
#e    5
#dtype: int64
#b    2
#c    3
#d    4
#dtype: int64
  • 如果想要获取最后三个元素,也可以使用下面的方式:
s = pd.Series([1,2,3,4,5],index = ['a','b','c','d','e'])
print(s[-3:])
#c    3
#d    4
#e    5
#dtype: int64
  • 通过标签切片的方式访问 Series 序列中的数据,示例如下:
  • 当 Series 使用标签切片时,其末端是包含的。
s1= pd.Series([6,7,8,9,10],index = ['a','b','c','d','e'])
s1["b":"d"]
#b    7
#c    8
#d    9
#dtype: int64
  • 如果首尾端一致的话,就是该元素本身。
s1= pd.Series([6,7,8,9,10],index = ['e','d','a','b','a'])
s1
#c    8
#dtype: int64
  • 在上面的索引方式,我们知道了位置索引和标签索引在 index 为数值类型时候的不同。
  • 当 index 为数值类型的时候,使用位置索引会抛出 keyerror 的异常,也就是说当 index 为数值类型的时候,索引使用的是名称索引。
  • 但是在切片的时候,有很大的不同,如果 index 为数值类型的时候,切片使用的是位置切片。
  • 总的来说,当 index 为数值类型的时候:
  • 进行索引的时候,相当于使用的是名称索引。
  • 进行切片的时候,相当于使用的是位置切片。

四、Series 数据结构的基本技巧

1. 查看前几条和后几条数据

s = pd.Series(np.random.rand(15))
s
#0    0.819404
#1    0.552555
#2    0.792454
#3    0.215595
#4    0.824303
#5    0.970804
#6    0.997465
#7    0.519955
#8    0.354990
#9    0.758266
#dtype: float64
  • s.head() 默认查看前 5 条数据,(其余的看括号内的数字)。
print(s.head())
print(s.head(1)) 
#0    0.819404
#1    0.552555
#2    0.792454
#3    0.215595
#4    0.824303
#dtype: float64
#0    0.819404
#dtype: float64
  • s.tail() 默认查看后 5 条数据(其余的看括号内的数字)。
print(s.tail()) 
#5    0.970804
#6    0.997465
#7    0.519955
#8    0.354990
#9    0.758266
#dtype: float64

2. 重新索引:reindex

  • 使用可选填充逻辑,使 Series 符合新索引。
  • 将 NaN 放在上一个索引中没有值的位置。除非新索引等同于当前索引,并且生成新对象。
  • 当新索引在上一个索引中不存在,生成新对象时,对应的值,设置为 NaN。
s = pd.Series(np.random.rand(5),index=list("abcde"))
s1 = s.reindex(list("cde"))
print("============s1=========")
print(s1)
print("============s=========")
print(s)
#============s1=========
#c    0.525886
#d    0.859566
#e    0.767330
#dtype: float64
#============s=========
#a    0.148972
#b    0.934014
#c    0.525886
#d    0.859566
#e    0.767330
#dtype: float64

3. 对齐运算

  • 对其运算是数据清洗的重要过程,可以按索引对齐进行运算,如果没对齐的位置则补 NaN,最后也可以填充 NaN。
s1 = pd.Series(np.random.rand(3), index=["Kelly","Anne","T-C"])​
s2 = pd.Series(np.random.rand(3), index=["Anne","Kelly","LiLy"])print("==========s1=========")
print(s1)
print("==========s2=========")
print(s2)
print("==========s1+s2=========")
print(s1+s2)
#==========s1=========
#Kelly    0.481159
#Anne     0.066326
#T-C      0.916705
#dtype: float64
#==========s2=========
#Anne     0.090194
#Kelly    0.150472
#LiLy     0.220991
#dtype: float64
#==========s1+s2=========
#Anne     0.156520
#Kelly    0.631632
#LiLy          NaN
#T-C           NaN
#dtype: float64

4. 删除和添加

  • s.drop() 是返回删除后的值,原值不改变,默认 inplace=False。
s = pd.Series(np.random.rand(5),index=list("abcde"))
s1 = s.drop("a")
print(s1) 
print(s)
#b    0.918685
#c    0.613762
#d    0.142165
#e    0.309032
#dtype: float64
#a    0.630504
#b    0.918685
#c    0.613762
#d    0.142165
#e    0.309032
#dtype: float64
  • 当 inplace 参数设置为 True 时,原值发生变化,返回 None。
s = pd.Series(np.random.rand(5),index=list("abcde"))
s1 = s.drop("a",inplace=True)
print(s1) 
print(s)
#None
#b    0.946778
#c    0.733088
#d    0.793721
#e    0.681853
#dtype: float64
  • 添加操作时,如果对应的标签没有就是添加,有就是修改。
s1 = pd.Series(np.random.rand(5),index=list("abcde"))
print(s1)​
s1["s"] = 100 
print(s1)
#a    0.743596
#b    0.778193
#c    0.036640
#d    0.324620
#e    0.282358
#dtype: float64
#a      0.743596
#b      0.778193
#c      0.036640
#d      0.324620
#e      0.282358
#s    100.000000
#dtype: float64

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

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

相关文章

WSL1和WSL2相互转换以及安装路径迁移相关问题

目录 1.从WSL 1如何切换到WSL 2&#xff1f; 2.从WSL 2如何切换回WSL 1&#xff1f; 3.WSL1转换为WSL2后&#xff0c;WSL1里面安装的程序和库需要重装吗&#xff1f; 4.WSL2转换为WSL1后&#xff0c;WSL2里面安装的程序和库需要重装吗&#xff1f; 5.如何备份WSL2&#xf…

【内网安全】——Windows权限维持

作者名&#xff1a;白昼安全主页面链接&#xff1a; 主页传送门创作初心&#xff1a; 以后赚大钱座右铭&#xff1a; 不要让时代的悲哀成为你的悲哀专研方向&#xff1a; web安全&#xff0c;后渗透技术每日鸡汤&#xff1a;20岁的年纪不该困在爱与不爱里&#xff0c;对吗在红队…

shiro CVE-2020-13933

0x00 前言 同CVE-2020-1957&#xff0c;补充一下笔记&#xff0c;在CVE-2020-1957的基础上进行了绕过。 影响版本&#xff1a;Apache Shiro < 1.6.0 环境搭建参考&#xff1a;shiro CVE-2020-1957 0x01 漏洞复现 CVE-2020-13933中使用%3b绕过了shiro /*的检测方式&…

使用BP神经网络和Elman Net预测航班价格(Matlab代码实现)

&#x1f468;‍&#x1f393;个人主页&#xff1a;研学社的博客&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5;&#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密…

电脑如何录制屏幕视频?6个屏幕录制的好方法

我们每天消费的大部分媒体都是通过视频。研究表明&#xff0c;与阅读相比&#xff0c;我们通过观看视频保留的信息更多。因此&#xff0c;很容易看出视频在我们的个人生活和职业生活中的重要性。 让我们更深入地了解视频录制软件和市场上的一些最佳选择。 如何确定好的视频录制…

建议收藏,轻松搞懂区块链

未来已来&#xff0c;只是不均衡地分布在当下 大家好&#xff0c;我是菜农&#xff0c;欢迎来到我的频道。 本文共 5844字&#xff0c;预计阅读 30 分钟 区块链是近些年来最热门的前沿技术&#xff0c;被认为是未来十几年对金融、物联网、医疗等诸多领域产生最大影响的"…

Similarity-Preserving KD(ICCV 2019)原理与代码解析

paper&#xff1a;Similarity-Preserving Knowledge Distillationcode&#xff1a;https://github.com/megvii-research/mdistiller/blob/master/mdistiller/distillers/SP.py背景本文的灵感来源于作者观察到在一个训练好的网络中&#xff0c;语义上相似的输入倾向于引起相似的…

[python入门㊾] - python异常中的断言

目录 ❤ 断言的功能与语法 ❤ 常用断言 ❤ 常用的断言表达方式 ❤ 异常断言 ❤ 正则断言 ❤ 检查断言装饰器 ❤ 断言的功能与语法 Python assert&#xff08;断言&#xff09;用于判断一个表达式&#xff0c;在表达式条件为 False 的时候触发异常 断言可以在条件…

2023Python接口自动化测试实战教程,附视频实战讲解

这两天一直在找直接用python做接口自动化的方法&#xff0c;在网上也搜了一些博客参考&#xff0c;今天自己动手试了一下。 一、整体结构 上图是项目的目录结构&#xff0c;下面主要介绍下每个目录的作用。 Common:公共方法:主要放置公共的操作的类&#xff0c;比如数据库sql…

js中数字运算结果与预期不一致的问题和解决方案

本文主要是和大家聊聊关于js中经常出现数字运算结果与预期结果不一致的问题&#xff0c;与及解决该问题的的方案。 一、问题现象 如&#xff1a;0.1 0.2的预期结果是0.3&#xff0c;但是在js中得到的计算结果却是0.30000000000000004&#xff0c;如下图所示 如&#xff1a;0…

GEE学习笔记 六十九:【GEE之Python版教程三】Python基础编程一

环境配置完成后&#xff0c;那么可以开始正式讲解编程知识。之前我在文章中也讲过&#xff0c;GEE的python版接口它是依赖python语言的。目前很多小伙伴是刚开始学习GEE编程&#xff0c;之前或者没有编程基础&#xff0c;或者是没有学习过python。为了照顾这批小伙伴&#xff0…

15种NLP数据增强方法总结与对比

数据增强的方法 数据增强&#xff08;Data Augmentation&#xff0c;简称DA&#xff09;&#xff0c;是指根据现有数据&#xff0c;合成新数据的一类方法。毕竟数据才是真正的效果天花板&#xff0c;有了更多数据后可以提升效果、增强模型泛化能力、提高鲁棒性等。然而由于NLP…

光伏VSG-基于虚拟同步发电机的光伏并网逆变器系统MATLAB仿真

采用MATLAB2021b仿真&#xff01;&#xff01;&#xff01;仿真模型1光伏电池模块&#xff08;采用MATLAB自带光伏模块&#xff09;、MPPT控制模块、升压模块、VSG控制模块、电流滞环控制模块。2s时改变光照强度 &#xff01;&#xff01;&#xff01;VSG输出有功功率、无功功率…

6.3 使用 Swagger 生成 Web API 文档

第6章 构建 RESTful 服务 6.1 RESTful 简介 6.2 构建 RESTful 应用接口 6.3 使用 Swagger 生成 Web API 文档 6.4 实战&#xff1a;实现 Web API 版本控制 6.3 使用 Swagger 生成 Web API 文档 高质量的 API 文档在系统开发的过程中非常重要。本节介绍什么是 Swagger&#xff…

15-基础加强-2-xml(约束)枚举注解

文章目录1.xml1.1概述【理解】(不用看)1.2标签的规则【应用】1.3语法规则【应用】1.4xml解析【应用】1.5DTD约束【理解】1.5.1 引入DTD约束的三种方法1.5.2 DTD语法&#xff08;会阅读&#xff0c;然后根据约束来写&#xff09;1.6 schema约束【理解】1.6.1 编写schema约束1.6.…

基于高频方波电压信号注入的永磁同步电机无传感器控制仿真及其原理介绍

基于方波信号注入的永磁同步电机无传感器控制仿真及其原理介绍 注入的高频方波信号为&#xff1a; 可以得到估计轴的高频响应电流为: 当向定子绕组注入高频电压信号时,所注入的高频信号频率远高于基波信号频率。因此&#xff0c;IPMSM 在a-β轴的电压模型可以表示为: 假定…

二叉树OJ(一)二叉树的最大深度 二叉搜索树与双向链表 对称的二叉树

二叉树的最大深度 二叉树中和为某一值的路径(一) 二叉搜索树与双向链表 对称的二叉树 二叉树的最大深度 描述 求给定二叉树的最大深度&#xff0c; 深度是指树的根节点到任一叶子节点路径上节点的数量。 最大深度是所有叶子节点的深度的最大值。 &#xff08;注&#xff1a;…

Xcode Archives打包上传 / 导出ipa 发布至TestFlight

Xcode自带的Archives工具可以傻瓜式上传到App Store Connect分发这里以分发到TestFlight为例进行操作。 环境&#xff1a;Xcode 14 一&#xff1a;Archives打包 选择Xcode菜单栏的Product&#xff0c;Archives选项&#xff0c;需要等待编译完成&#xff0c;进入如下界面&…

【C语言】初识结构体

☃️内容专栏&#xff1a;【C语言】初阶部分 ☃️本文概括&#xff1a;继初识C语言&#xff0c;对C语言结构体初阶部分进行归纳与总结。 ☃️本文作者&#xff1a;花香碟自来_ ☃️发布时间&#xff1a;2023.2.19 一、结构体的声明 结构体&#xff08;类型&#xff09;是一些…

字符设备驱动基础(二)

目录 一、五种IO模型------读写外设数据的方式 二、阻塞与非阻塞 三、多路复用 3.1 应用层&#xff1a;三套接口select、poll、epoll 3.2 驱动层&#xff1a;实现poll函数 四、信号驱动 4.1 应用层&#xff1a;信号注册fcntl 4.2 驱动层&#xff1a;实现fasync函数 一、…