C语言动态顺序表:从结构定义到全功能实现

阿橙
阿橙
发布时间:2026-10-15| 6人浏览过
原创

顺序表是线性表的一种存储实现,分为静态和动态两类。静态顺序表容量固定,难以兼顾空间利用与扩展性;动态顺序表则基于指针和数组,支持随数据量自动增容。本文将深入解析 C语言 中动态顺序表的底层结构设计,并提供包含初始化、增删查改及内存安全处理的完整实现方案。

顺序表概念及结构

顺序表采用物理地址连续的存储单元依次存放数据元素,通常以数组为底。其分类主要依据存储空间是否可变:

  • 静态顺序表:编译时确定大小,用完即满且无法扩缩,存在空间不足或资源浪费的矛盾。
  • 动态顺序表:底层使用指向动态开辟数组的指针。当空间满时进行增容(通常为原大小的2倍),解决了容量限制并优化了空间利用率。

动态顺序表的核心结构需维护三个关键状态:动态数组首地址、当前有效数据量以及当前总容量。

基本操作与接口定义

为实现完整的顺序表管理,需定义类型别名及结构体,并封装初始化和销毁函数以确保数据安全。

  1. 结构体定义:使用 typedef struct 定义 SeqList,内部包含 SLDateType* a(指针域)、size_t size(有效大小)和 size_t capacity(总容量)。
  2. 辅助函数:定义 Check_Capacity 专责检查并执行扩容逻辑,其他功能函数在此基础之上调用。
  3. 核心接口:Init 初始化、Destroy 释放内存、Print 打印数据,以及针对头部、尾部及任意位置的插入与删除操作。

第1步:结构体与安全声明配置

在头文件中进行宏保护与依赖引入,建立类型别名以便于后续修改数据类型。

#pragma once
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>

typedef int SLDateType;

typedef struct SeqList
{
	SLDateType* a;     // 维护动态开辟的数组
	size_t size;       // 有效数据的数量
	size_t capacity;   // 当前分配的总空间大小
}SeqList;

第2步:容量检查与自动扩容逻辑

所有涉及插入数据的操作前,必须调用此检查函数。若已满或初次插入,触发扩容并更新指针与容量值。

static void Check_Capacity(SeqList* ps)
{
    if (ps->capacity == ps->size) 
    {
        // 初次创建或满了都需要扩容,最少分配4个单位
        size_t NewCapacity = (ps->capacity == 0) ? 4 : ps->capacity * 2;
        
        int* tmp = (int*)realloc(ps->a, NewCapacity * sizeof(int));
        if (tmp == NULL)
            exit(-1);
            
        ps->a = tmp;
        ps->capacity = NewCapacity;
    }
}

第3步:初始化与销毁的安全处理

初始化将所有指针置为空,计数归零;销毁时务必先释放动态内存再重置成员变量,防止野指针和内存泄漏。

void SeqListInit(SeqList* ps)
{
    assert(ps);
    ps->a = NULL;
    ps->capacity = 0;
    ps->size = 0;
}

void SeqListDestroy(SeqList* ps)
{
    assert(ps);
    free(ps->a); // 必须先释放堆上内存
    ps->capacity = 0;
    ps->size = 0;
}

第4步:数据的插入与维护(头/尾插)

插入前均需先检查容量。尾插简单直接;头插需要将原有数据向后移动一位以腾出位置。

// 尾插法
void SeqListPushBack(SeqList* ps, SLDateType x)
{
    assert(ps);
    Check_Capacity(ps);
    ps->a[ps->size] = x;
    ps->size++;
}

// 头插法
void SeqListPushFront(SeqList* ps, SLDateType x)
{
    assert(ps);
    Check_Capacity(ps);
    // 将末尾之前的所有元素向后挪动
    int end = ps->size - 1;
    for (; end >= 0; end--)
        ps->a[end + 1] = ps->a[end];
    ps->a[0] = x; // 或者 ps->a[end + 1] = x;
    ps->size++;
}

第5步:数据删除与位置操作

删除时需验证链表非空。头删是将后续元素向前覆盖;指定位置插入/删除同样伴随大量的元素搬移操作,需注意边界条件验证。

// 尾删
void SeqListPopBack(SeqList* ps)
{
    assert(ps);
    assert(ps->size > 0);
    ps->size--;
}

// 指定位置插入
void SeqListInsert(SeqList* ps, size_t pos, SLDateType x)
{
    assert(ps);
    assert(pos <= ps->size); // 防止越界访问
    Check_Capacity(ps);
    
    int end = ps->size - 1;
    int target = (int)pos;
    for (; end >= target; end--)
        ps->a[end + 1] = ps->a[end];
    ps->a[target] = x;
    ps->size++;
}

// 指定位置删除
void SeqListErase(SeqList* ps, size_t pos)
{
    assert(ps);
    assert(ps->size > 0);
    assert(pos < ps->size); 
    
    int begin = (int)pos + 1;
    int len = ps->size;
    for (; begin < len; begin++)
        ps->a[begin - 1] = ps->a[begin];
    ps->size--;
}

程序运行效果

在完成上述接口定义与功能实现后,在主函数中依次调用初始化、插入多个节点、查找、中间插入及删除等操作,最后打印验证输出结果是否正确反映了各次操作后的内存状态。

以上就是C语言动态顺序表的详细内容,更多关于C语言顺序表实现资料请关注本站其它相关文章!

相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。