数据结构入门:顺序表专题详解

数据结构入门:顺序表专题详解

顺序表是数据结构中最基础的一种线性结构,底层基于数组实现。本文将系统讲解顺序表的概念、分类,并带你从零实现一个动态顺序表,掌握增删改查等核心操作。

目录


一、数据结构预备知识

1. 为什么学数据结构?

通讯录等项目中需要管理数据(增加、删除、修改、查找),仅靠C语言基础无法高效完成。数据结构提供了组织和管理数据的有效方式。

2. 数据结构相关概念

  • 数据:数值、用户信息、文字、图片等。
  • 结构:组织数据的方式。例如羊圈将羊群有效组织,数组将大量数据组织在一起。
  • 数据结构:计算机存储、组织数据的方式,反映数据间的特定关系。

3. 为什么需要数据结构?

不管理数据会导致数据丢失、操作困难、野指针等问题。数据结构能按需对数据进行增删改查。

思考 :有了数组,为什么还要学习其他数据结构?

数组操作需要频繁获取有效数据个数、判断容量等,数据量大时效率低。更高级的数据结构能提供更高效的接口。


二、顺序表概念及结构

线性表

线性表是 n 个具有相同特性的数据元素的有限序列,逻辑上连续(一条直线),物理上不一定连续。常见的线性表有:顺序表、链表、栈、队列、字符串等。

顺序表底层是数组,是对数组的封装,实现了增删改查等接口


三、顺序表分类

1. 静态顺序表

使用定长数组存储元素。

缺陷:空间给少了不够用,给多了造成浪费。

c 复制代码
#define MAX_SIZE 100
typedef struct {
    int data[MAX_SIZE];
    int size;        // 有效数据个数
} SeqListStatic;

2. 动态顺序表

按需申请空间,可动态扩容,避免了空间浪费或不足。

c 复制代码
typedef int SLDataType;
typedef struct SeqList {
    SLDataType* a;   // 指向动态数组的指针
    int size;        // 有效数据个数
    int capacity;    // 当前空间容量
} SL;

四、实现动态顺序表

4.1 基本结构定义

c 复制代码
#define INIT_CAPACITY 4

typedef int SLDataType;
typedef struct SeqList {
    SLDataType* a;
    int size;      // 有效数据个数
    int capacity;  // 空间容量
} SL;

4.2 接口函数声明

c 复制代码
// 初始化和销毁
void SLInit(SL* ps);
void SLDestroy(SL* ps);
void SLPrint(SL* ps);

// 扩容检查
void SLCheckCapacity(SL* ps);

// 头部插入/删除、尾部插入/删除
void SLPushBack(SL* ps, SLDataType x);
void SLPopBack(SL* ps);
void SLPushFront(SL* ps, SLDataType x);
void SLPopFront(SL* ps);

// 指定位置之前插入/删除
void SLInsert(SL* ps, int pos, SLDataType x);
void SLErase(SL* ps, int pos);

4.3 核心实现代码

初始化与销毁
c 复制代码
void SLInit(SL* ps) {
    ps->a = NULL;
    ps->size = 0;
    ps->capacity = 0;
}

void SLDestroy(SL* ps) {
    if (ps->a) {
        free(ps->a);
        ps->a = NULL;
    }
    ps->size = ps->capacity = 0;
}
扩容检查

每次插入前检查容量,不足则扩容(通常翻倍)

c 复制代码
void SLCheckCapacity(SL* ps) {
    if (ps->size == ps->capacity) {
        int newCapacity = (ps->capacity == 0) ? INIT_CAPACITY : ps->capacity * 2;
        SLDataType* tmp = (SLDataType*)realloc(ps->a, newCapacity * sizeof(SLDataType));
        if (tmp == NULL) {
            perror("realloc fail");
            return;
        }
        ps->a = tmp;
        ps->capacity = newCapacity;
    }
}
尾插
c 复制代码
void SLPushBack(SL* ps, SLDataType x) {
    SLCheckCapacity(ps);
    ps->a[ps->size] = x;
    ps->size++;
}
尾删
c 复制代码
void SLPopBack(SL* ps) {
    assert(ps->size > 0);  // 顺序表不能为空
    ps->size--;
}
头插
c 复制代码
void SLPushFront(SL* ps, SLDataType x) {
    SLCheckCapacity(ps);
    // 将所有元素后移一位
    for (int i = ps->size; i > 0; i--) {
        ps->a[i] = ps->a[i-1];
    }
    ps->a[0] = x;
    ps->size++;
}
头删
c 复制代码
void SLPopFront(SL* ps) {
    assert(ps->size > 0);
    for (int i = 0; i < ps->size - 1; i++) {
        ps->a[i] = ps->a[i+1];
    }
    ps->size--;
}
指定位置插入
c 复制代码
void SLInsert(SL* ps, int pos, SLDataType x) {
    assert(pos >= 0 && pos <= ps->size);
    SLCheckCapacity(ps);
    for (int i = ps->size; i > pos; i--) {
        ps->a[i] = ps->a[i-1];
    }
    ps->a[pos] = x;
    ps->size++;
}
指定位置删除
c 复制代码
void SLErase(SL* ps, int pos) {
    assert(pos >= 0 && pos < ps->size);
    for (int i = pos; i < ps->size - 1; i++) {
        ps->a[i] = ps->a[i+1];
    }
    ps->size--;
}
打印顺序表
c 复制代码
void SLPrint(SL* ps) {
    for (int i = 0; i < ps->size; i++) {
        printf("%d ", ps->a[i]);
    }
    printf("\n");
}

4.4 完整使用示例

c 复制代码
int main() {
    SL sl;
    SLInit(&sl);
    
    SLPushBack(&sl, 1);
    SLPushBack(&sl, 2);
    SLPushBack(&sl, 3);
    SLPrint(&sl);   // 1 2 3
    
    SLPushFront(&sl, 0);
    SLPrint(&sl);   // 0 1 2 3
    
    SLInsert(&sl, 2, 99);
    SLPrint(&sl);   // 0 1 99 2 3
    
    SLErase(&sl, 2);
    SLPrint(&sl);   // 0 1 2 3
    
    SLDestroy(&sl);
    return 0;
}

总结:顺序表是一种线性数据结构,底层使用动态数组实现。相比静态数组,动态顺序表能够按需扩容,避免空间浪费。通过封装初始化、销毁、增删改查等接口,可以高效管理数据。掌握顺序表是实现更复杂数据结构(如链表、栈、队列)的基础。注意检查容量、防止越界、及时释放内存等细节。

相关推荐
刘马想放假3 天前
Modbus 全栈技术解析:TCP、RTU、ASCII、RTU over TCP
数据结构·网络协议
北域码匠4 天前
冒泡排序太慢?鸡尾酒排序双向优化,原生 C# 零第三方库完整代码
数据结构·排序算法·泛型·c# 算法·鸡尾酒排序·原生 c# 开发·冒泡排序优化·嵌入式算法
Darling噜啦啦11 天前
列表转树算法深度解析:从 Map 到 Reduce 的两种实现,面试高频考点
数据结构·算法·面试
小小工匠12 天前
Redis - 事务机制:能实现 ACID 属性吗
数据结构·redis·性能优化·并发·持久化
玖玥拾12 天前
C/C++ 数据结构(七)栈、容器适配器
c语言·数据结构·c++··容器适配器
Qres82112 天前
算法复键——树状数组
数据结构·算法
牛油果子哥q12 天前
并查集(DSU)超精讲,路径压缩、按秩合并、万能模板、连通性判定、最小生成树与刷题实战全解
数据结构·c++·最小生成树·并查集
凌波粒12 天前
LeetCode--491.递增子序列(回溯算法)
数据结构·算法·leetcode
WL学习笔记12 天前
单项不带头不循环链表
数据结构·链表
小糯米60112 天前
JS 数组
数据结构·算法·排序算法