当前位置: 首页 > news >正文

大话数据结构之 <顺序表> (C语言)

引言:数据结构是计算机科学中研究数据组织、存储和操作方式的一门学科,它关注如何高效地管理数据,以支持各种常见的操作(如插入、删除、查找、排序等)。无论是软件开发、算法设计还是人工智能等领域,数据结构都是核心基础。本专题陆续更新初阶数据结构,并附有简单实现代码(C语言版),帮助理解。

首先,C语言基础不牢的建议打牢C语言基础。

其次,结构体部分理解不深的可以看一下我的另一篇文章:自定义类型: 结 构 体 -CSDN博客

线性表

  • 线性表(linear list)是n个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使用的数据结 构,常见的线性表:顺序表、链表、栈、队列、字符串...
  • 线性表在逻辑上是线性结构,也就说是连续的一条直线。但是在物理结构上并不一定是连续的,线性表在物 理上存储时,通常以数组和链式结构的形式存储。


顺序表

概念及结构
  1. 顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组存储。在数组上完成数据的增删查改。
  2. 顺序表是一种线性数据结构,它用一段连续的内存空间依次存储数据元素,是数组的抽象实现(静态数组或动态扩容数组均可视为顺序表)。其核心特点是元素的逻辑顺序与物理存储顺序一致,通过下标(索引) 可直接访问元素。
顺序表一般可以分为:

1. 静态顺序表:使用定长数组存储元素

  • 定义时指定固定长度(如int arr[10]),内存空间在编译时分配。
  • 缺点:长度固定,元素数量超过容量时会溢出,灵活性差。
#define MAXSIZE 100
typedef struct {int data[MAXSIZE];int length;
} SqList;

静态顺序表的核心缺点源于其容量固定连续存储的特性,这使其在灵活性、内存利用率和动态操作效率上存在明显不足。实际开发中,静态顺序表更适合数据量固定、访问频繁但增删较少的场景(如存储常量数据、固定大小的配置信息等)

 2. 动态顺序表:使用动态开辟的数组存储。

  • 初始分配一定内存,当元素满时自动扩容(如翻倍申请新空间,复制旧元素后释放原空间)。
  • 优点:长度动态调整,避免溢出,更贴合实际需求(如 Java 的ArrayList、Python 的list本质都是动态顺序表)。

静态顺序表只适用于确定知道需要存多少数据的场景。静态顺序表的定长数组导致N定大了,空间开多了浪 费,开少了不够用。所以现实中基本都是使用动态顺序表,根据需要动态的分配空间大小,所以下面我们实现动态顺序表。

主要实现增删查改操作:

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>//简单实现--顺序表
//顺序表和链表作为初学的两个最基础的数据结构//实现一个顺序表需要的基本操作 
/*   1.初始化2.销毁 3.打印4.检查顺序表的容量,是否需要扩容5.尾插6.尾删7.头插8.头删9.pos位置插入10.pos位置删除11.查找 
*/typedef int SLDataType;
#define INIT_CAPACITY 4// 动态顺序表 -- 按需申请
typedef struct SeqList
{SLDataType* a; //指向一块连续的空间 int size;     // 有效数据个数int capacity; // 空间容量
}SL;// 增删查改//1.顺序表初始化 
void SLInit(SL* ps)
{ps->a = (SLDataType*)malloc(sizeof(SLDataType)*INIT_CAPACITY);if(ps->a == NULL){perror("malloc fail");return;}ps->size = 0;ps->capacity = INIT_CAPACITY;}//2.顺序表销毁 
void SLDestroy(SL* ps)
{assert(ps);free(ps);ps->a =NULL;ps->size = ps->capacity = 0;
}//3.打印 
void SLPrint(SL* ps)
{assert(ps);int i = 0;for(i = 0;i < ps->size;i++){printf("%d ",ps->a[i]);} 
}//4.扩容 
void SLCheckCapacity(SL* ps)
{assert(ps);if(ps->capacity == ps->size){SLDataType* tmp = (SLDataType*)realloc(ps->a,sizeof(SLDataType)*ps->capacity*2);if(tmp == NULL){perror("realloc fail");return;}ps->a = tmp;ps->capacity *= 2;}	}//5.尾插 
void SLPushBack(SL* ps, SLDataType x)
{SLCheckCapacity(ps);ps->a[ps->size] = x;ps->size++; }//6.尾删 
void SLPopBack(SL* ps)
{assert(ps);ps->a[ps->size-1] = 0;ps->size--;
} //7.头插 
void SLPushFront(SL* ps, SLDataType x)
{assert(ps); SLCheckCapacity(ps);int end = ps->size-1;while(end>=0){ps->a[end+1] = ps->a[end];end--;}ps->a[0] = x;ps->size++;
}//8.头删 
void SLPopFront(SL* ps)
{assert(ps);assert(ps->size > 0);int begin = 1;while (begin < ps->size){ps->a[begin - 1] = ps->a[begin];++begin;}ps->size--;
}//9.在pos位置插入 
void SLInsert(SL* ps, int pos, SLDataType x)
{assert(ps);assert(pos >= 0 && pos <= ps->size);SLCheckCapacity(ps);int end = ps->size - 1;while (end >= pos){ps->a[end + 1] = ps->a[end];--end;}ps->a[pos] = x;ps->size++;
}//10.pos位置删除 
void SLErase(SL* ps, int pos)
{assert(ps);	assert(pos >= 0 && pos < ps->size);int begin = pos + 1;while (begin < ps->size){		ps->a[begin - 1] = ps->a[begin];		++begin;	}ps->size--;}//11.查找 
int SLFind(SL* ps, SLDataType x)
{assert(ps);int i = 0;for(i = 0; i < ps->size; ++i){if (ps->a[i] == x){return i;}}return -1;
}int main()
{SL sl;//现在我们来实现一下 整个顺序表//首先尾插5个数据 SLPushBack(&sl,1);SLPushBack(&sl,2);	 SLPushBack(&sl,3);	SLPushBack(&sl,4);	SLPushBack(&sl,5);//打印出来看一下SLPrint(&sl);printf("\n"); //头插5个数据SLPushFront(&sl,5);SLPushFront(&sl,6);SLPushFront(&sl,7);SLPushFront(&sl,8);SLPushFront(&sl,9);//打印出来看一下SLPrint(&sl);printf("\n");//头删两个数据 SLPopFront(&sl);SLPopFront(&sl);//尾删三个数据SLPopBack(&sl);SLPopBack(&sl);		SLPopBack(&sl);	SLPrint(&sl);printf("\n");//销毁顺序表
//	SLDestroy(&sl);		return 0;} 

应用场景

顺序表适用于:

  • 元素数量相对固定

  • 需要频繁随机访问

  • 插入和删除操作较少

时间复杂度总结

操作时间复杂度
访问元素O(1)
插入元素O(n)
删除元素O(n)
按值查找O(n)
按位查找O(1)
http://www.dtcms.com/a/277766.html

相关文章:

  • 学习:JS基础[5]对象
  • 【SpringAI Alibaba】基于 Redis 实现连续对话与向量存储
  • VsCode的LivePreview插件应用
  • [Java恶补day41] 226. 翻转二叉树
  • 基于springboot的大学公文收发管理系统
  • AB实验评估指标体系之【实验评估指标体系】
  • 015_引用功能与信息溯源
  • python 字典(Dictionary) vs. 集合(Set):它们是如何做到快速查找的?为什么字典的键(key)必须是不可变的?
  • S7-1200 与 ET200SP:PROFINET 设备关键数据 IP 地址、MAC 地址及 MRP 环状态获取
  • Datawhale AI 夏令营2025科大讯飞AI大赛<夏令营:用AI做带货视频评论分析>
  • 什么是渐进式框架
  • OpenVela 之 UI 应用开发
  • kettle从入门到精通 第102课 ETL之kettle xxl-job调度kettle的两种方式
  • 【Linux系统】进程状态 | 进程优先级
  • 手写std::optional:告别空指针的痛苦
  • java + groovy : 动态解析groovy脚本,并与java交互
  • MacBook Air M4 安装 VMware Fusion Pro
  • 问题记录:Fastjson序列化-空值字段处理
  • CA复习功课
  • Appdynamic 配置 PostgreSQL 收集器
  • 复习笔记 34
  • 【VSCode+LaTeX】科研写作环境搭建
  • 内存池(C++)v3 | 简历写法 | 相关面试题
  • 浏览器本地存储——使用localStorage实现电商系统商品收藏功能实战
  • 在网站学装机
  • SCTP协议网络编程
  • 从源码看Nginx:Nginx事件驱动架构深度拆解来了
  • linux上的软挂载操作方法
  • Docker 快速上手
  • 【elementUI踩坑记录】解决 el-table 固定列 el-table__fixed 导致部分滚动条无法拖动的问题