#数据结构----2.1线性表

发布于:2025-09-06 ⋅ 阅读:(19) ⋅ 点赞:(0)

在数据结构的学习中,线性表是最基础、最核心的结构之一 —— 它是后续栈、队列、链表等复杂结构的 “基石”。今天从 “是什么”(定义)到 “怎么用”(基本操作),彻底搞懂线性表的核心逻辑。

image-20250904160511892

一、先明确:数据结构的三要素

在聊线性表之前,必须先记住数据结构的核心三要素,这是理解所有结构的前提:

逻辑结构:数据元素之间的 “关系”(比如线性表的 “前后顺序”);

数据的运算:对数据元素能做的操作(比如增、删、改、查);

存储结构(物理结构):数据在内存中的 “存放方式”(比如数组、链表)。

关键提醒:存储结构不同,运算的实现方式也不同(比如数组实现和链表实现的 “插入” 操作,底层逻辑完全不一样),但今天我们先聚焦 “逻辑结构” 和 “运算”。

二、线性表的定义:到底什么是线性表?

线性表是具有相同数据类型的 n(n≥0)个数据元素的有限序列,用 L 命名时可表示为:

( L = (a_1, a_2, …, a_i, a_{i+1}, …, a_n) )

我们拆解这个定义里的关键信息,再结合例子理解会更透彻:

1. 定义的 3 个核心特性

  • 同类型:所有元素的数据类型必须一致(比如全是整数、全是学生信息);

  • 有限性:元素个数 n 是有限的(不存在无限个元素的线性表);

  • 有序性:元素之间有明确的 “前后顺序”(a₁ 在 a₂ 前面,a₂ 在 a₃ 前面,不能乱序)。

2. 几个必须分清的术语

术语 含义
表长 线性表中元素的个数 n(n=0 时为空表)
表头元素 第一个元素 a₁
表尾元素 最后一个元素 aₙ
直接前驱 除 a₁ 外,每个元素 aᵢ 前面的那个元素(即 aᵢ₋₁)
直接后继 除 aₙ 外,每个元素 aᵢ 后面的那个元素(即 aᵢ₊₁)
位序 元素在表中的 “位置编号”(从 1 开始!和数组下标从 0 开始形成区别)

image-20250904161656732

3. 举个例子:哪些是线性表?

  • 例 1:所有整数按递增顺序排列(1,2,3,4,…100)—— 同类型(整数)、有限(100 个)、有序(递增),是线性表;

  • 例 2:学生信息表(如下表)—— 同类型(学生信息)、有限(10 条记录)、有序(按学号排序),是线性表;

学号 姓名 专业
1120112100 张三 挖掘机
1120112101 李四 挖掘机
1120112102 王玉玉 数据挖掘
  • 例 3:学习计划列表(学习《C 语言》→ 学习《数据结构》→ 学习《架构师》)—— 同类型(学习任务)、有限、有序,也是线性表。

三、线性表的基本操作:从 “创” 到 “销” 全流程

为什么要定义基本操作?核心原因有两个:

  1. 团队协作:封装好的操作能让其他人直接用,不用重复理解底层逻辑;

  2. 减少错误:常用操作写成函数,避免重复编码导致的 bug。

线性表的操作可以按 “生命周期” 和 “功能” 分为 4 类,我们逐个拆解(重点关注 “是否需要传引用 &”):

1. 创销类:线性表的 “出生” 与 “消亡”

这两类操作是线性表的基础 —— 从 “无” 到 “有”,再从 “有” 到 “无”。

  • InitList (&L):初始化表

功能:构造一个空的线性表 L,并为其分配内存空间。

为什么传 &L?因为要修改 L 本身(给它分配内存、设置表长为 0),需要把修改结果 “带回来”。

  • DestroyList (&L):销毁表

功能:销毁线性表 L,并释放它占用的内存空间(避免内存泄漏)。

为什么传 &L?因为要释放 L 指向的内存,修改 L 的状态(比如让 L 指向 NULL),需要带回报错结果。

2. 增删类:改变线性表的 “长度”

这两类操作会修改线性表的元素个数,是高频操作。

  • ListInsert (&L, i, e):插入元素

功能:在表 L 的第 i 个位置,插入新元素 e(插入后表长 +1)。

传参说明:&L(要修改表的结构)、i(插入位置,需满足 1≤i≤表长 + 1)、e(要插入的元素)。

  • ListDelete (&L, i, &e):删除元素

功能:删除表 L 第 i 个位置的元素,并用 e 保存被删除元素的值(删除后表长 -1)。

为什么 &e?因为要把 “被删除的元素值” 带回来(比如用户需要知道删了什么)。

3. 改查类:定位元素(“改” 的前提是 “查”)

“查” 是 “改” 的基础 —— 要修改元素,必须先找到它的位置或值。

  • GetElem (L, i):按位查找

功能:获取表 L 第 i 个位置的元素值(i 需满足 1≤i≤表长)。

为什么不传 &L?因为只是 “读取” 元素,没有修改表的结构或内容,不需要带回结果。

  • LocateElem (L, e):按值查找

功能:在表 L 中查找 “值等于 e” 的元素,返回它的位序(若找不到返回 0 或 NULL)。

同理,仅读取,不传 &L。

4. 其他常用操作:辅助功能

这些操作是对线性表的 “补充查询”,高频且实用:

  • Length (L):求表长:返回表 L 中元素的个数 n;

  • PrintList (L):输出表:按前后顺序打印所有元素(比如打印学生信息表);

  • Empty (L):判空:若表 L 为空(n=0)返回 true,否则返回 false。

关键考点:什么时候传引用 “&”?

当对参数的修改结果需要 “带回来” 时,必须传引用(或指针)

比如:

  • 不传 & 的情况:调用 test(x) 后,x 的值在主函数中不变(修改只在 test 内部生效);

    #include<stdio.h>
    void test(int x){
    	x=1024;
    	printf("test函数内部 x=%d\n",x);
    }
    int main(){
    	int x=1;
    	printf("调用test前 x=%d\n",x);
    	test(x);
    	printf("调用test后x=%d\n",x);
    }
    

    image-20250904162212940

    image-20250904162318877

  • 传 & 的情况:调用 test(&x) 后,x 的值在主函数中会被修改(修改结果带回来了)。

    #include<stdio.h>
    void test(int & x){
        x=1024;
        printf("test函数内部 x=%d\n",x);
    }
    int main(){
        int x=1;
        printf("调用test前 x=%d\n",x);
        test(x);
        printf("调用test后x=%d\n",x);
    }
    

    image-20250904163012076

    image-20250904163027336

对应到线性表操作:

需要传 &L 的操作:InitList、DestroyList、ListInsert、ListDelete(都修改了 L 的结构或内容);

不需要传 &L 的操作:GetElem、LocateElem、Length、PrintList、Empty(仅读取,不修改)。

四、总结:线性表的核心要点

逻辑结构核心:同类型、有限、有序,每个元素(除首尾)有唯一前驱和后继;

操作记忆思路:按 “创销→增删→改查” 的生命周期记忆,辅助 “判空、表长、打印”;

传参关键:修改需 “带回结果” 则传 &,仅读取则不传;

注意细节:位序从 1 开始(和数组下标区分),函数命名要可读(比如 InitList 比 fun1 更易理解)。



网站公告

今日签到

点亮在社区的每一天
去签到