数据结构分类
逻辑结构:线性与非线性
逻辑结构揭示了数据元素之间的逻辑关系。
- 线性数据结构:数组、链表、栈、队列、哈希表,元素之间是一对一的顺序关系。
- 非线性数据结构:树、堆、图、哈希表。
从存储的角度来看,哈希表的底层是数组,其中每一个桶槽位可能包含一个值,也可能包含一个链表或一棵树。因此,哈希表可能同时包含线性数据结构(数组、链表)和非线性数据结构(树)。
非线性数据结构可以进一步划分为树形结构和网状结构。
- 树形结构:树、堆、哈希表,元素之间是一对多的关系。
- 网状结构:图,元素之间是多对多的关系。
物理结构:连续与分散
当算法程序运行时,正在处理的数据主要存储在内存中
系统通过内存地址来访问目标位置的数据
内存是所有程序的共享资源,当某块内存被某个程序占用时,则通常无法被其他程序同时使用了。因此在数据结构与算法的设计中,内存资源是一个重要的考虑因素
物理结构反映了数据在计算机内存中的存储方式,可分为连续空间存储(数组)和分散空间存储(链表)。
所有数据结构都是基于数组、链表或二者的组合实现的
- 基于数组可实现:栈、队列、哈希表、树、堆、图、矩阵、张量(维度 的数组)等。
- 基于链表可实现:栈、队列、哈希表、树、堆、图等。
基本数据类型
基本数据类型是 CPU 可以直接进行运算的类型,在算法中直接被使用,主要包括以下几种。
- 整数类型
byte、short、int、long。 - 浮点数类型
float、double,用于表示小数。 - 字符类型
char,用于表示各种语言的字母、标点符号甚至表情符号等。 - 布尔类型
bool,用于表示“是”与“否”判断。
基本数据类型以二进制的形式存储在计算机中。一个二进制位即为 1 比特。在绝大多数现代操作系统中,1 字节(byte)由 8 比特(bit)组成。
数字编码
原码、反码和补码
数字是以“补码”的形式存储在计算机中的。
- 原码:我们将数字的二进制表示的最高位视为符号位,其中 0 表示正数,1 表示负数,其余位表示数字的值。
- 反码:正数的反码与其原码相同,负数的反码是对其原码除符号位外的所有位取反。
- 补码:正数的补码与其原码相同,负数的补码是在其反码的基础上加 1 。
字符编码
在计算机中,所有数据都是以二进制数的形式存储的。为了表示字符,我们需要建立一套“字符集”,规定每个字符和二进制数之间的一一对应关系。
ASCII 字符集
ASCII 码使用 7 位二进制数(一个字节的低 7 位)表示一个字符,最多能够表示 128 个不同的字符。ASCII 码包括英文字母的大小写、数字 0 ~ 9、一些标点符号,以及一些控制字符(如换行符和制表符)。
ASCII 码仅能够表示英文。
GBK 字符集
中国国家标准总局于 1980 年发布了 GB2312 字符集,其收录了 6763 个汉字,基本满足了汉字的计算机处理需要。
GB2312 无法处理部分罕见字和繁体字。GBK 字符集是在 GB2312 的基础上扩展得到的,它共收录了 21886 个汉字。在 GBK 的编码方案中,ASCII 字符使用一个字节表示,汉字使用两个字节表示。
Unicode 字符集
Unicode 的中文名称为“统一码”
UTF-8 编码
目前,UTF-8 已成为国际上使用最广泛的 Unicode 编码方法。它是一种可变长度的编码,使用 1 到 4 字节来表示一个字符,根据字符的复杂性而变。ASCII 字符只需 1 字节,拉丁字母和希腊字母需要 2 字节,常用的中文字符需要 3 字节,其他的一些生僻字符需要 4 字节。
- UTF-16 编码:使用 2 或 4 字节来表示一个字符。所有的 ASCII 字符和常用的非英文字符,都用 2 字节表示;少数字符需要用到 4 字节表示。对于 2 字节的字符,UTF-16 编码与 Unicode 码点相等。
- UTF-32 编码:每个字符都使用 4 字节。这意味着 UTF-32 比 UTF-8 和 UTF-16 更占用空间,特别是对于 ASCII 字符占比较高的文本。
编程语言的字符编码
JavaScript 和 TypeScript 的字符串使用 UTF-16 编码。当 1995 年 Netscape 公司首次推出 JavaScript 语言时,Unicode 还处于发展早期,那时候使用 16 位的编码就足以表示所有的 Unicode 字符了。