您现在的位置是:首页 >学无止境 >Hello算法学习之数据结构网站首页学无止境
Hello算法学习之数据结构
一、数据结构
数据结构分为逻辑结构(「逻辑结构」揭示了数据元素之间的逻辑关系)和物理结构(「物理结构」反映了数据在计算机内存中的存储方式)
1.逻辑结构
逻辑结构分为线性和非线性结构:
- 线性数据结构:数组、链表、栈、队列、哈希表;数据按照顺序依次排序
- 非线性数据结构:树、图、堆、哈希表
哈希表底层是数组,所以包含线性数据结构。而为了解决哈希冲突,我们可能会使用“拉链法”(后续散列表章节会讲)。在拉链法中,数组中每个地址(桶)指向一个链表;当这个链表长度超过一定阈值时,又可能被转化为树(常为红黑树)。因此,哈希表可能同时包含线性(数组、链表)和非线性(树)数据结构。
2.物理结构
物理结构分为连续和离散结构:数组的连续空间存储和链表的离散空间存储。物理结构从底层决定了数据的访问、更新、增删等操作方法,同时在时间效率和空间效率方面呈现出互补的特点。
所有数据结构都是基于数组、链表或二者的组合实现的。例如,栈和队列既可以使用数组实现,也可以使用链表实现;而哈希表的实现可能同时包含数组和链表。
- 基于数组可实现(静态数据结构,初始化后长度不可变):栈、队列、哈希表、树、堆、图、矩阵、张量(维度 ≥3 的数组)等;
- 基于链表可实现(动态数据结构,初始化后长度可以调整):栈、队列、哈希表、树、堆、图等;
二、基本数据类型
基本数据类型是 CPU 可以直接进行运算的类型,在算法中直接被使用。它包括:
- 整数类型
byte
,short
,int
,long
; - 浮点数类型
float
,double
,用于表示小数; - 字符类型
char
,用于表示各种语言的字母、标点符号、甚至表情符号等; - 布尔类型
bool
,用于表示“是”与“否”判断;
所有基本数据类型都以二进制的形式存储在计算机中。将 1 个二进制位称为 1 比特,并规定 1 字节(byte)由 8 比特(bits)组成。
基本数据类型的取值范围取决于其占用的空间大小,例如:
- 整数类型
byte
占用 1 byte = 8 bits ,可以表示 2的8次方 个不同的数字; - 整数类型
int
占用 4 bytes = 32 bits ,可以表示 2的32次方个数字;
基本数据类型提供了数据的“内容类型”,而数据结构提供了数据的“组织方式”比如想要表达“一排数字”,那么我们会想到使用数组这个结构。
三、数字编码
1、原码、反码和补码
- 原码:我们将数字的二进制表示的最高位视为符号位,其中 0 表示正数,1 表示负数,其余位表示数字的值。
- 反码:正数的反码与其原码相同,负数的反码是对其原码除符号位外的所有位取反。
- 补码:正数的补码与其原码相同,负数的补码是在其反码的基础上加 1 。
数字是以补码的形式存储在计算机中的。
反码是为了解决计算问题,补码是为了解决反码中0分为+0和-0的问题
所有整数类型能够表示的负数都比正数多一个。例如,byte
的取值范围是 [−128,127] 。这是因为补码 1000 0000 没有对应的原码。计算机规定这个特殊的补码 1000 0000 代表 −128 。实际上,(−1)+(−127) 在补码下的计算结果就是 −128 。
2、浮点数编码
根据 IEEE 754 标准,32-bit 长度的 float
由以下部分构成:
- 符号位 S :占 1 bit ;
- 指数位 E :占 8 bits ;
- 分数位 N :占 24 bits ,其中 23 位显式存储;
由于float的表示方式包含指数位,所以它的范围远大于int。但尽管浮点数 float
扩展了取值范围,但其副作用是牺牲了精度。整数类型 int
将全部 32 位用于表示数字,数字是均匀分布的;而由于指数位的存在,浮点数 float
的数值越大,相邻两个数字之间的差值就会趋向越大。
四、字符编码
1、ASCII字符集
它使用 7 位二进制数(即一个字节的低 7 位)表示一个字符,最多能够表示 128 个不同的字符。随着计算机的全球化,诞生了一种能够表示更多语言的字符集「EASCII」。它在 ASCII 的 7 位基础上扩展到 8 位,能够表示 256 个不同的字符。在世界范围内,陆续出现了一批适用于不同地区的 EASCII 字符集。这些字符集的前 128 个字符统一为 ASCII 码,后 128 个字符定义不同,以适应不同语言的需求。
2、GBK字符集
ASCII 字符使用一个字节表示,汉字使用两个字节表示。
3、 Unicode 字符集
在庞大的 Unicode 字符集中,常用的字符占用 2 字节,有些生僻的字符占 3 字节甚至 4 字节。
Unicode 是一种字符集标准,本质上是给每个字符分配一个编号(称为“码点”),但它并没有规定在计算机中如何存储这些字符码点。(所以会产生一个问题,当给计算机8位的编码时,它怎么能知道这是一个2字节的字符,还是两个1字节的字符呢?)。所以,unicode将所有字符存储为等长的编码,不足的高位补齐
4、 UTF-8 编码(解决unicode占用内存空间大的问题)
它是一种可变长的编码,使用 1 到 4 个字节来表示一个字符,根据字符的复杂性而变。ASCII 字符只需要 1 个字节,拉丁字母和希腊字母需要 2 个字节,常用的中文字符需要 3 个字节,其他的一些生僻字符需要 4 个字节。
UTF-8 的编码规则分为两种情况:
- 对于长度为 1 字节的字符,将最高位设置为 0 、其余 7 位设置为 Unicode 码点。值得注意的是,ASCII 字符在 Unicode 字符集中占据了前 128 个码点。也就是说,UTF-8 编码可以向下兼容 ASCII 码。这意味着我们可以使用 UTF-8 来解析年代久远的 ASCII 码文本。
- 对于长度为n字节的字符(其中 n>1),将首个字节的高 n位都设置为 1 、第 n+1 位设置为 0 ;从第二个字节开始,将每个字节的高 2 位都设置为 10 ;其余所有位用于填充字符的 Unicode 码点。
常见的编码方式还包括 UTF-16 和 UTF-32 。它们为 Unicode 字符集提供了不同的编码方法。
- UTF-16 编码:使用 2 或 4 个字节来表示一个字符。所有的 ASCII 字符和很多常用的非英文字符,都用 2 个字节表示;少数字符需要用到 4 个字节表示。对于 2 字节的字符,UTF-16 编码与 Unicode 码点相等。
- UTF-32 编码:每个字符都使用 4 个字节。这意味着 UTF-32 会比 UTF-8 和 UTF-16 更占用空间,特别是对于主要使用 ASCII 字符的文本。
浮点数编码和 编程语言的字符编码没有太懂,等学完之后再回头看一下