顺序表笔记

一、学习顺序表的核心目的

学习数据结构的核心诉求是解决程序运行的效率问题与算法实现的基础支撑问题,而顺序表作为线性表的基础实现形式,是理解这两个核心的关键起点:

  1. 效率优化:原生数组在处理大规模数据时,插入 / 删除元素需移动大量数据、无法灵活统计有效数据个数,顺序表通过封装数组并规范操作逻辑,可针对性优化这些场景的时间 / 空间效率;
  2. 算法基础:栈、队列等常用数据结构的底层可基于顺序表实现,掌握顺序表是后续学习复杂算法(如排序、查找)的必要前提。

二、顺序表的核心概念

1. 定义

顺序表本质是对原生数组的封装,通过结构体整合 "存储数据的数组" 和 "记录有效数据个数的变量",并封装增、删、查、改等操作,让数组的使用更规范、高效。

2. 分类

根据存储空间的灵活性,顺序表分为两类:

类型 特点
静态顺序表 数组长度通过宏定义(如#define N 10)固定,存储空间编译时确定,无法动态扩容
动态顺序表 用数组指针指向存储空间,新增 "容量变量" 记录空间大小,可按需扩容,空间利用率更高

三、顺序表的核心实现(C 语言)

1. 基础结构定义

(1)静态顺序表
复制代码
#include <stdio.h>
#include <stdlib.h>

// 宏定义数组长度(静态顺序表固定长度)
#define MAX_SIZE 10

// 定义静态顺序表结构体
typedef struct {
    int data[MAX_SIZE];  // 存储数据的数组
    int size;            // 有效数据个数
} StaticSeqList;
(2)动态顺序表
复制代码
// 定义动态顺序表结构体
typedef struct {
    int* data;   // 指向存储数据的数组
    int size;    // 有效数据个数
    int capacity;// 数组总容量(存储空间大小)
} DynamicSeqList;

2. 核心操作实现

(1)初始化

初始化的核心是将 "有效数据个数置 0",动态顺序表需额外初始化存储空间:

复制代码
// 静态顺序表初始化
void InitStaticSeqList(StaticSeqList* list) {
    if (list == NULL) return;
    list->size = 0;  // 有效数据个数初始化为0
}

// 动态顺序表初始化(初始容量设为8)
int InitDynamicSeqList(DynamicSeqList* list) {
    if (list == NULL) return -1;
    list->capacity = 8;
    list->data = (int*)malloc(sizeof(int) * list->capacity);
    if (list->data == NULL) return -1;  // 内存分配失败
    list->size = 0;
    return 0;
}
(2)增加元素(尾部插入 + 指定位置插入)

增加元素的核心逻辑:先检查存储空间是否已满→验证位置合法性→插入元素→更新有效数据个数。

复制代码
// 静态顺序表尾部插入
int StaticPushBack(StaticSeqList* list, int value) {
    // 检查顺序表是否已满
    if (list == NULL || list->size >= MAX_SIZE) return -1;
    list->data[list->size] = value;  // 插入到尾部
    list->size++;                    // 有效个数+1
    return 0;
}

// 静态顺序表指定位置插入(pos从0开始)
int StaticInsert(StaticSeqList* list, int pos, int value) {
    // 检查合法性:指针非空、位置合法、顺序表未满
    if (list == NULL || pos < 0 || pos > list->size || list->size >= MAX_SIZE) return -1;
    // 从后往前移动元素,为插入位置腾出空间
    for (int i = list->size; i > pos; i--) {
        list->data[i] = list->data[i-1];
    }
    list->data[pos] = value;  // 插入元素
    list->size++;            // 有效个数+1
    return 0;
}
(3)删除元素

删除的核心逻辑:验证位置合法性→移动元素覆盖待删除值→更新有效数据个数。

复制代码
// 静态顺序表删除指定位置元素
int StaticDelete(StaticSeqList* list, int pos) {
    if (list == NULL || pos < 0 || pos >= list->size) return -1;
    // 从删除位置往后,元素依次前移
    for (int i = pos; i < list->size - 1; i++) {
        list->data[i] = list->data[i+1];
    }
    list->size--;  // 有效个数-1
    return 0;
}
(4)查找与修改
复制代码
// 查找元素:返回第一个匹配值的下标,未找到返回-1
int StaticFind(StaticSeqList* list, int value) {
    if (list == NULL) return -1;
    for (int i = 0; i < list->size; i++) {
        if (list->data[i] == value) {
            return i;
        }
    }
    return -1;
}

// 修改指定位置元素值
int StaticModify(StaticSeqList* list, int pos, int newValue) {
    if (list == NULL || pos < 0 || pos >= list->size) return -1;
    list->data[pos] = newValue;
    return 0;
}
(5)测试示例
复制代码
int main() {
    // 静态顺序表测试
    StaticSeqList list;
    InitStaticSeqList(&list);  // 初始化
    
    // 尾部插入元素
    StaticPushBack(&list, 10);
    StaticPushBack(&list, 20);
    // 指定位置插入(下标1插入15)
    StaticInsert(&list, 1, 15);
    
    // 查找元素20的位置
    int findPos = StaticFind(&list, 20);
    printf("元素20的下标:%d\n", findPos);  // 输出:2
    
    // 修改下标1的元素为18
    StaticModify(&list, 1, 18);
    
    // 删除下标2的元素
    StaticDelete(&list, 2);
    
    // 遍历输出所有元素
    printf("顺序表元素:");
    for (int i = 0; i < list->size; i++) {
        printf("%d ", list.data[i]);  // 输出:10 18
    }
    
    return 0;
}
相关推荐
JieE21218 小时前
LeetCode 56. 合并区间|超清晰 JS 图解思路,面试高频区间题
javascript·算法·面试
Jack201 天前
HarmonyOS开发中错误处理策略:网络异常统一处理
算法
小小杨树1 天前
读懂色彩:拍照调色不再难
算法·计算机视觉·配色
JieE2122 天前
LeetCode 226. 翻转二叉树|JS 递归超详细拆解,二叉树入门经典题
javascript·算法
JieE2122 天前
LeetCode 104. 二叉树的最大深度|递归思路超详细拆解
javascript·算法
vivo互联网技术2 天前
CVPR 2026 | 全新强化学习框架 BeautyGRPO:重塑真实人像
算法·大模型·cvpr·影像
Darling噜啦啦2 天前
列表转树算法深度解析:从 Map 到 Reduce 的两种实现,面试高频考点
数据结构·算法·面试
用户497863050732 天前
(一)小红的数组操作
算法·编程语言
怕浪猫2 天前
Electron 系列文章封面图
算法·架构·前端框架