📘 第六章 · 数组

谭浩强《C程序设计》第五版 — 交互式教学演示

📋第六章知识体系总览

  • 数组的概念与意义
  • 一维数组的定义与初始化
  • 数组元素的引用与遍历
  • 二维数组(矩阵)
  • 字符数组与字符串
  • 字符串处理函数
  • 冒泡排序 / 选择排序
  • 顺序查找 / 折半查找
💡 核心思想:数组是同类型数据的有序集合,在内存中连续存放。 下标从 0 开始,越界访问是常见 Bug 来源,务必注意!

📌 数组变量的意义

为什么需要数组?

📌 集中管理:假设要存储 100 个学生的成绩,用 int s1,s2,...,s100 需要 100 个变量名;而用 int score[100] 只需一个名字 + 下标,代码更简洁。

📌 批量处理:结合循环,数组可以用 for 循环批量访问(如计算平均分、找最大值),而普通变量只能逐个单独操作。

📌 内存连续:数组元素在内存中紧密排列,CPU 缓存命中率高,遍历效率远高于分散的变量。

🗺️本章学习路线图

① 概念
什么是数组
② 定义
类型 名[长度]
③ 初始化
{ } 赋值
④ 引用
a[i] 访问
⑤ 算法
排序/查找
⑥ 字符串
字符数组
学习建议:按顶部标签页顺序逐节学习,每节均有可交互的动画演示, 学完后务必完成各节「随堂测验」!

✏️随堂小测验 — 章节概览

🔢一维数组的定义与初始化

/* 定义格式:类型符 数组名[常量表达式]; */ int a[5]; // 定义 5 个 int 型元素的数组 float score[10]; // 定义 10 个 float 型元素的数组 /* 初始化示例 */ int b[5] = {10, 20, 30, 40, 50}; int c[5] = {1, 2}; // 其余元素自动置 0 → {1,2,0,0,0} int d[] = {3, 6, 9, 12, 15}; // 长度由初值个数决定,为 5
⚠️ 注意:数组下标从 0 开始,最大合法下标为 长度-1a[5] 的合法范围是 a[0] ~ a[4],访问 a[5] 是越界!

🏗️内存布局可视化

点击「生成数组」随机填充 5 元素数组,再点击任意格子高亮对应内存地址:

点击上方数组格子,查看元素的内存地址和值。

🔄数组遍历演示

用 for 循环逐个访问 5 元素数组,光标会逐格扫描:

int a[5] = {15, 42, 8, 73, 51}; for (int i = 0; i < 5; i++) printf("a[%d] = %d\n", i, a[i]);
准备就绪,点击「开始遍历」演示 for 循环扫描过程。

✏️随堂小测验 — 一维数组

🧮二维数组的定义与存储

/* 定义:类型符 数组名[行数][列数]; */ int a[3][4]; // 3行4列,共12个元素 /* 初始化 —— 按行分组 */ int b[3][4] = { {1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12} }; /* 访问元素 */ printf("%d", b[1][2]); // 输出第2行第3列 = 7
📌 二维数组在内存中按行存放:先存第0行,再存第1行…… a[i][j] 的地址 = 基址 + (i × 列数 + j) × sizeof(元素类型)

🖥️矩阵可视化演示

点击格子高亮;点击「行序遍历」查看内存顺序:

点击矩阵中的格子,或使用按钮演示遍历过程。

📐矩阵转置

/* 将矩阵 a 转置后存入 b */ for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) b[j][i] = a[i][j];
原矩阵 A
转置矩阵 B
点击「执行转置」查看动画效果。

✏️随堂小测验 — 二维数组

📝字符数组与字符串

/* 字符数组定义 */ char s1[6] = {'H','e','l','l','o','\0'}; char s2[6] = "Hello"; // 等效写法,自动加 '\0' /* 常用字符串函数(#include )*/ strlen(s) // 字符串长度(不含 '\0') strcpy(dst, src) // 拷贝 strcat(s1, s2) // 拼接 strcmp(s1, s2) // 比较(返回 0 表示相等)
🔑 关键:C语言字符串以 \0(空字符)结尾。 char s[5]="Hello" 只能存4个字符,因为最后必须留位置给 '\0'!

🔬字符串内存结构演示

选择一个字符串,观察每个字符的存储情况(包括结尾的 \0)。

🔧字符串函数交互练习

选择操作,实时查看函数执行结果。

✏️随堂小测验 — 字符数组

⚙️排序算法演示

选择排序算法,观察 5 元素数组的逐步排序过程:

选择一种排序方式,点击按钮开始演示。

📄冒泡排序代码

void bubbleSort(int a[], int n) { int i, j, temp; for (i = 0; i < n-1; i++) { for (j = 0; j < n-1-i; j++) { if (a[j] > a[j+1]) { // 相邻两数比较 temp = a[j]; // 三步交换 a[j] = a[j+1]; a[j+1] = temp; } } } }
🕐 复杂度:时间复杂度 O(n²),空间复杂度 O(1)。 每轮外层循环后,最大值"冒泡"到末尾,已排序区域逐渐扩大。

📄选择排序代码

void selectionSort(int a[], int n) { int i, j, minIdx, temp; for (i = 0; i < n-1; i++) { minIdx = i; for (j = i+1; j < n; j++) if (a[j] < a[minIdx]) minIdx = j; temp = a[i]; a[i] = a[minIdx]; a[minIdx] = temp; } }

✏️随堂小测验 — 排序算法

🔍顺序查找

int seqSearch(int a[], int n, int key) { for (int i = 0; i < n; i++) if (a[i] == key) return i; // 找到,返回下标 return -1; // 未找到,返回 -1 }
填入要查找的值,点击「开始查找」观察逐个比较的过程。

折半查找(二分查找)

前提:数组必须是有序数组!每次比较可排除一半数据,效率远高于顺序查找。 时间复杂度 O(log n)。
int binarySearch(int a[], int n, int key) { int low = 0, high = n-1, mid; while (low <= high) { mid = (low + high) / 2; if (a[mid] == key) return mid; else if (a[mid] < key) low = mid + 1; else high = mid - 1; } return -1; }
填入要查找的值,观察折半区间的收缩过程。

✏️随堂小测验 — 查找算法

🧠随堂测验 — 第六章数组

第 1 题 / 共 8 题 得分:0