2·基础概念入门

数组基础

arrayindextraverse

第 2 课:数组基础

学习目标

完成本课学习后,你将能够:

  1. 理解数组的定义和基本特性。
  2. 掌握数组的声明、初始化和访问元素的方法。
  3. 熟练使用循环(如 for 循环)遍历数组。
  4. 理解索引(Index)的概念,并能正确使用索引操作数组。
  5. 了解数组在内存中的存储方式及其优缺点。

核心概念

什么是数组?

想象你有一个书架,上面有一排连续的格子,每个格子都可以存放一本书。数组就像这样一个书架:它是一个线性数据结构,用于存储相同类型固定数量的元素,这些元素在内存中连续存放

数组中的每个元素都有一个唯一的编号,叫做索引(Index),通过索引我们可以快速访问(读取或修改)对应的元素。大多数编程语言中,数组的索引是从 0 开始的。

数组的内存模型

当你在程序中声明一个数组时,计算机会在内存中分配一块连续的空间来存储这些元素。假设一个整型数组 arr 有 5 个元素,每个整数占 4 个字节,那么它的内存布局如下:

索引:    0     1     2     3     4
内存:  [4B]  [4B]  [4B]  [4B]  [4B]  <- 连续的内存块
值:     ?     ?     ?     ?     ?      <- 初始化前的值(可能是随机值)

关键点:因为内存是连续的,所以通过计算 起始地址 + 索引 * 每个元素大小,可以在 O(1) 时间内直接定位到任意元素,这是数组最大的优点。

数组的声明与初始化(以 Python 为例)

在 Python 中,我们通常使用 列表(List) 来表示数组。列表在功能上类似于其他语言的数组,但更灵活(如长度可变、可存放不同类型元素)。为了学习基础数据结构,我们将 Python 列表当作数组来使用。

# 方法1:直接赋值初始化
scores = [90, 85, 78, 92, 88]  # 创建一个包含5个整数的“数组”

# 方法2:创建一个空列表,后续添加元素
names = []

# 方法3:使用列表推导式(模拟固定大小初始化)
zeros = [0 for _ in range(10)]  # 创建一个包含10个0的数组

代码示例

示例1:数组的创建、访问与遍历

# 创建一个存储学生成绩的数组
grades = [85, 92, 78, 95, 88]

# 1. 访问数组元素(通过索引)
print("第一个学生的成绩:", grades[0])  # 输出: 85 (索引从0开始)
print("第三个学生的成绩:", grades[2])  # 输出: 78
print("最后一个学生的成绩:", grades[4])  # 输出: 88

# 也可以使用负索引从末尾访问
print("最后一个学生的成绩(负索引):", grades[-1])  # 输出: 88

# 2. 修改数组元素
grades[0] = 88  # 将第一个学生的成绩从85改为88
print("修改后的成绩数组:", grades)  # 输出: [88, 92, 78, 95, 88]

# 3. 获取数组长度
print("学生总数:", len(grades))  # 输出: 5

# 4. 遍历数组(使用for循环)
print("\n所有学生的成绩:")
for i in range(len(grades)):  # 方法1:通过索引遍历
    print(f"学生 {i+1} 的成绩: {grades[i]}")

print("\n使用enumerate遍历:")
for index, grade in enumerate(grades):  # 方法2:更Pythonic的方式
    print(f"学生 {index+1} 的成绩: {grade}")

示例2:一个简单的数组应用——计算平均分

def calculate_average(arr):
    """计算数组的平均值"""
    if len(arr) == 0:  # 处理空数组的情况
        return 0
    total = 0
    for score in arr:
        total += score  # 累加每个元素
    return total / len(arr)  # 总和除以元素个数

# 使用示例
scores = [78, 85, 92, 67, 95]
average = calculate_average(scores)
print(f"成绩数组: {scores}")
print(f"平均分: {average:.2f}")  # 格式化为两位小数

输出

成绩数组: [78, 85, 92, 67, 95]
平均分: 83.40

实践练习

练习1:基础操作 - 数组元素统计

编写一个函数,接收一个数字数组,返回该数组中的最大值最小值总和

def array_stats(numbers):
    # 在这里编写你的代码
    # 提示:先处理空数组的情况
    # 遍历数组,比较更新最大值和最小值,同时累加总和
    pass

# 测试用例
test_array = [3, 7, 1, 9, 4]
result = array_stats(test_array)
print(f"数组: {test_array}")
print(f"最大值: {result['max']}")  # 预期: 9
print(f"最小值: {result['min']}")  # 预期: 1
print(f"总和: {result['sum']}")    # 预期: 24

练习2:进阶操作 - 数组反转

编写一个函数,将输入的数组原地反转(不使用额外的数组空间)。

def reverse_array(arr):
    # 在这里编写你的代码
    # 提示:使用两个指针,一个在开头,一个在末尾,交换它们指向的元素,然后逐步向中间移动
    pass

# 测试用例
original = [1, 2, 3, 4, 5]
print(f"反转前: {original}")
reverse_array(original)
print(f"反转后: {original}")  # 预期: [5, 4, 3, 2, 1]

练习3:挑战 - 二维数组遍历

以下是一个 3x4 的二维数组(矩阵),编写代码按行优先的顺序遍历并打印所有元素。

matrix = [
    [1, 2, 3, 4],
    [5, 6, 7, 8],
    [9, 10, 11, 12]
]

# 你的遍历代码应该输出:
# 1 2 3 4
# 5 6 7 8
# 9 10 11 12

常见错误

  1. 索引越界(Index Out of Bounds)

    arr = [1, 2, 3]
    print(arr[3])  # 错误!有效索引是0,1,2
    

    解决方案:始终记得数组长度是 n,有效索引是 0n-1

  2. 混淆索引和元素值

    arr = [10, 20, 30]
    # 错误:试图用元素值作为索引
    index = 20  # 这是一个值,不是索引
    print(arr[index])  # 可能导致意外结果或错误
    
  3. 忽略数组的连续性假设 在 Python 列表中,虽然元素在逻辑上是连续的,但实际存储的是对象的引用。对于真正的数组(如 C 语言的数组),必须存储相同大小的元素。

  4. 忘记数组长度固定(在某些语言中) 在 C、Java 等语言中,数组创建后长度不可变。Python 列表可以动态增长,但理解基础数组的固定长度特性对学习很重要。

小结

本课我们学习了数组的基础知识:

  • 数组是一种存储相同类型元素的线性数据结构,元素在内存中连续存放
  • 通过索引(从0开始)可以在 O(1) 时间内访问任意元素。
  • 数组的声明、初始化和遍历是所有操作的基础。
  • 遍历数组通常使用 for 循环,可以是索引遍历或元素遍历。
  • 数组的主要优点是快速随机访问,主要缺点是固定大小(在非动态数组中)和插入/删除效率低(需要移动元素)。

掌握了数组,你就拥有了处理大量同类型数据的基本工具。下一课,我们将学习链表,了解另一种线性数据结构,它与数组有互补的特性。

练习编辑器

rust
Loading...

继续学习

完成本课后,建议继续学习下一课「链表」 以巩固所学知识。