目录

学习目标

引言

1.什么是线性表?

2.什么是顺序表?

2.1概念及结构

2.2 接口实现

2.2.1顺序表的功能

1.顺序表的初始化

2.打印数据

3.尾插数据

(1)检查空间

(2)插入数据

4.尾删数据

5.头插数据

6.头删数据

7.数据查找

8.指定位置数据修改

9.指定位置数据删除

10.指定位置数据插入

11.销毁顺序表

完整代码

1.SeqList.h

2.SeqList.c

2.3 数组相关面试题

2.4 顺序表的问题及思考

结束语


学习目标

  • 1.什么是线性表?
  • 什么是顺序表?
  • 顺序表的接口实现

引言

在 数据结构——lesson1.基础中我们学习了数据结构的一些基础知识,今天我们接着来学习一种数据结构——顺序表

在学习顺序表之前,我们首先要知道

1.什么是线性表

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

2.什么是顺序表?

2.1概念及结构

顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组存储。在数组上完成数据的增删查改。

顺序表一般可以分为:

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

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

今天我们要学习的是动态顺序表

它与数组非常类似,但是相比于静态顺序表有一个非常明显的优点——可以动态内存增长空间大小。

2.2 接口实现

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

2.2.1顺序表的功能

顺序表可以大致包含如下几个功能:

1.初始化顺序表中的数据。

2.打印顺序表中的数据。

3.对顺序表进行尾插(末尾插入数据)。

4.对顺序表进行尾删(末尾删除数据)。

5.对顺序表进行头插(开头插入数据)。

6.对顺序表进行头删(开头删除数据)。

7.对顺序表数据进行查找。

8.对顺序表数据进行修改。

9.对指定位置的数据删除。

10.对指定位置的数据插入。

11.销毁顺序表。

1.顺序表的初始化

代码实现

顺序表的初始化我们可以把空间和有效数据个数都设置为0。

void SLInit(SL* ps)
{ps->arr = NULL;ps->size = ps->capacity = 0;
}

2.打印数据

代码实现

//顺序表的打印
void SLPrint(SL* ps)
{assert(ps);if (ps->size == 0){printf("该顺序表为空\n");return;}for (int i = 0; i < ps->size; i++){printf("%d ", ps->arr[i]);}printf("\n");
}

3.尾插数据

尾插数据就是在顺序表的末尾插入数据,在插入数据之前需要先检查顺序表的空间够不够,不够的话我们需要进行扩容处理。

(1)检查空间
void SLCheckCapacity(SL* ps)
{//插入数据之前先看空间够不够if (ps->capacity == ps->size){//申请空间//malloc calloc realloc int arr[100]--->增容realloc//三目表达式int newCapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;//创建一个变量,避免申请失败SLDataType* tmp = (SLDataType*)realloc(ps->arr, newCapacity * sizeof(SLDataType));//判断是否成功if (tmp == NULL){perror("realloc fail:");exit(1);	//直接退出程序,不再执行}ps->arr = tmp;ps->capacity = newCapacity;}
}
(2)插入数据
//尾插
void SLPushBack(SL* ps, SLDataType x)
{assert(ps);SLCheckCapacity(ps);    //检查空间是否足够//ps->arr[ps->size] = x;//++ps->size;ps->arr[ps->size++] = x;    //尾插数据
}

4.尾删数据

尾删数据十分容易,只需要size--就可以了。但是,要注意:一定要确保顺序表中有数据

void SLPopBack(SL* ps)
{assert(ps);//判断顺序表是否为空assert(ps->size);ps->size--;
}

5.头插数据

头插数据是指在顺序表的起始位置插入数据。

//头插
void SLPushFront(SL* ps, SLDataType x)
{assert(ps);SLCheckCapacity(ps);//让顺序表中已经存在的数据整体往后挪一位for (int i = ps->size; i > 0; i--){ps->arr[i] = ps->arr[i - 1];	//即arr[1]=arr[0]以此类推}ps->arr[0] = x;ps->size++;
}

6.头删数据

删除头部数据,需要依次往前覆盖。

// 头删
void SLPopFront(SL* ps)
{assert(ps);//判断顺序表是否为空assert(ps->size);//数据整体往前移动一位for (int i = 0; i < ps->size - 1; i++){ps->arr[i] = ps->arr[i + 1];}ps->size--;
}

7.数据查找

输入参数,在顺序表找到指定的值并返回下标,找不到则返回-1。

//顺序表的查找
int SLFind(SL* ps, SLDataType x)
{assert(ps);for (int i = 0; i < ps->size; i++){//找到if (ps->arr[i] == x){return i;}}//没找到return -1;
}

8.指定位置数据修改

//指定位置数据修改
void SLModify(SL* ps, int pos, SLDataType x)
{assert(ps);assert(ps->size);assert(pos>=0 && pos < ps->size);ps->arr[pos] = x;
}

9.指定位置数据删除

//指定位置删除数据
void SLErase(SL* ps, int pos)
{assert(ps);assert(pos >= 0 && pos < ps->size);for (int i = pos; i < ps->size - 1; i++){ps->arr[i] = ps->arr[i + 1];}ps->size--;  //有效数据-1
}

10.指定位置数据插入

//在指定位置之前插入数据
//pos为指定位置
void SLInsert(SL* ps, int pos, SLDataType x)
{assert(ps);assert(pos >= 0 && pos <= ps->size);//先检查空间够不够SLCheckCapacity(ps);//让pos及之后的数据整体向后移动一位for (int i = ps->size; i > pos; i--){ps->arr[i] = ps->arr[i - 1];}ps->arr[pos] = x;ps->size++;
}

11.销毁顺序表

//顺序表的销毁
void SLDestroy(SL* ps)
{if (ps->arr){free(ps->arr);}ps->arr = NULL;ps->size = ps->capacity = 0;
}

完整代码

1.SeqList.h

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>//定义顺序表的结构//define N 100
//静态顺序表
//struct SeqList
//{
//	int arr[N];
//	int size;	//有效数据个数
//}typedef int SLDataType;
//动态顺序表
typedef struct SeqList
{SLDataType* arr;int size;		//有效数据个数int capacity;	//空间大小
}SL;//顺序表初始化
void SLInit(SL* ps);
//顺序表的销毁
void SLDestroy(SL* PS);
//顺序表的打印
void SLPrint(SL s);//尾部插入
void SLPushBack(SL* ps, SLDataType x);
//头部插入
void SLPushFront(SL* ps, SLDataType x);//尾部删除
void SLPopBack(SL* ps);
//头部删除
void SLPopFront(SL* ps);//指定位置之前插入
void SLInsert(SL* ps, int pos, SLDataType x);
//指定位置删除数据
void SLErase(SL* ps, int pos);
//查找数据
int SLFind(SL* ps, SLDataType x);

2.SeqList.c

#include"SeqList.h"void SLInit(SL* ps)
{ps->arr = NULL;ps->size = ps->capacity = 0;
}//顺序表的销毁
void SLDestroy(SL* ps)
{if (ps->arr){free(ps->arr);}ps->arr = NULL;ps->size = ps->capacity = 0;
}void SLCheckCapacity(SL* ps)
{//插入数据之前先看空间够不够if (ps->capacity == ps->size){//申请空间//malloc calloc realloc int arr[100]--->增容realloc//三目表达式int newCapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;//创建一个变量,避免申请失败SLDataType* tmp = (SLDataType*)realloc(ps->arr, newCapacity * sizeof(SLDataType));//判断是否成功if (tmp == NULL){perror("realloc fail:");exit(1);	//直接退出程序,不再执行}ps->arr = tmp;ps->capacity = newCapacity;}
}//尾插
void SLPushBack(SL* ps, SLDataType x)
{/*if (ps == NULL){return;}*/assert(ps);/*ps->arr[ps->size] = x;++ps->size;*/SLCheckCapacity(ps);ps->arr[ps->size++] = x;
}//头插
void SLPushFront(SL* ps, SLDataType x)
{assert(ps);SLCheckCapacity(ps);//让顺序表中已经存在的数据整体往后挪一位for (int i = ps->size; i > 0; i--){ps->arr[i] = ps->arr[i - 1];	//即arr[1]=arr[0]以此类推}ps->arr[0] = x;ps->size++;
}//顺序表的打印
void SLPrint(SL* ps)
{assert(ps);if (ps->size == 0){printf("该顺序表为空\n");return;}for (int i = 0; i < ps->size; i++){printf("%d ", ps->arr[i]);}printf("\n");
}void SLPopBack(SL* ps)
{assert(ps);//判断顺序表是否为空assert(ps->size);ps->size--;
}// 头删
void SLPopFront(SL* ps)
{assert(ps);//判断顺序表是否为空assert(ps->size);//数据整体往前移动一位for (int i = 0; i < ps->size - 1; i++){ps->arr[i] = ps->arr[i + 1];}ps->size--;
}//在指定位置之前插入数据
//pos为指定位置
void SLInsert(SL* ps, int pos, SLDataType x)
{assert(ps);assert(pos >= 0 && pos <= ps->size);//先检查空间够不够SLCheckCapacity(ps);//让pos及之后的数据整体向后移动一位for (int i = ps->size; i > pos; i--){ps->arr[i] = ps->arr[i - 1];}ps->arr[pos] = x;ps->size++;
}//指定位置删除数据
void SLErase(SL* ps, int pos)
{assert(ps);assert(pos >= 0 && pos < ps->size);for (int i = pos; i < ps->size - 1; i++){ps->arr[i] = ps->arr[i + 1];}ps->size--;  
}//顺序表的查找
int SLFind(SL* ps, SLDataType x)
{assert(ps);for (int i = 0; i < ps->size; i++){//找到if (ps->arr[i] == x){return i;}}//没找到return -1;
}//指定位置数据修改
void SLModify(SL* ps, int pos, SLDataType x)
{assert(ps);assert(ps->size);assert(pos>=0 && pos < ps->size);ps->arr[pos] = x;
}

2.3 数组相关面试题

  • . 原地移除数组中所有的元素val,要求时间复杂度为O(N),空间复杂度为O(1)。OJ链接
  • 2. 删除排序数组中的重复项。OJ链接
  • 3. 合并两个有序数组。OJ链接

2.4 顺序表的问题及思考

问题:

  • 1. 中间/头部的插入删除,时间复杂度为O(N)
  • 2. 增容需要申请新空间,拷贝数据,释放旧空间。会有不小的消耗。
  • 3. 增容一般是呈2倍的增长,势必会有一定的空间浪费。例如当前容量为100,满了以后增容到200,我们 再继续插入了5个数据,后面没有数据插入了,那么就浪费了95个数据空间。

思考:如何解决以上问题呢?下一节内容我们将给出了链表的结构来看看。

结束语

这一节我们了解到了第一个数据结构——顺序表

非常感谢你的点赞关注和收藏!!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/pingmian/96150.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/96150.shtml
英文地址,请注明出处:http://en.pswp.cn/pingmian/96150.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ChatGPT大模型训练指南:如何借助动态代理IP提高训练效率

随着人工智能技术的飞速发展&#xff0c;ChatGPT等大型语言模型&#xff08;LLM&#xff09;已成为科技界和产业界关注的焦点。模型的训练过程耗时、耗资源且对网络环境要求极高。尤其是在需要模拟真实用户行为、进行大规模数据爬取或分布式训练的场景下&#xff0c;单一IP地址…

Docker 学习笔记(六):多容器管理与集群部署实践

Docker Docker-compose 单个 Dockerfile 可定义单容器应用&#xff0c;但日常工作中&#xff0c;Web 项目等常需 Web 服务、数据库、负载均衡等多容器配合&#xff0c;手动按序启停容器会导致维护量大、效率低。 Docker Compose 是高效的多容器管理工具&#xff0c;通过单个 do…

C++类和对象初识

面向过程 1.1 面向过程特点 1.2 通俗解释&#xff1a;煮方便面 1.3 面向过程实现代码 1.4 特点总结面向对象 2.1 面向对象特点 2.2 通俗解释&#xff1a;对象协作思维 2.3 面向对象实现代码 2.4 特点总结面向对象和面向过程总结C 面向对象介绍 4.1 面向对象三大基本特征封装&am…

C++ Int128 —— 128位有符号整数类实现剖析

&#x1f9e0; C Int128 —— 128位有符号整数类实现剖析 引用&#xff1a;openppp2/ppp/Int128.h &#x1f3d7;️ 1. 存储结构设计 #mermaid-svg-2JDFsdz6MTbX253D {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-sv…

【C 语言生成指定范围随机数(整数 + 小数):原理、实现与避坑指南】

概述 在 C 语言开发中&#xff0c;生成指定范围的随机数是高频需求&#xff08;如游戏随机道具、数据模拟、测试用例生成等&#xff09;。但很多新手会卡在 “范围控制”“随机数重复”“小数生成” 等问题上。本文结合实战场景&#xff0c;从原理到代码详细讲解如何生成 1100、…

一个简单的langgraph agent系统

本文基于langgraph的预制件 Agent Chat UI和《搭建一个本地langgraph服务》中的本地服务构建一个简单的agent系统。 说明&#xff1a;Agent Chat UI需要nodejs版本18及以上&#xff0c;而nodejs18需要的glibc版本为2.28&#xff0c;本人使用操作系统为ubuntu18.04&#xff0c;g…

通过SSH来推送本地文件夹到Github

配置SSH git使用SSH配置&#xff0c; 初始需要以下三个步骤 使用秘钥生成工具生成rsa秘钥和公钥 将rsa公钥添加到代码托管平台 将rsa秘钥添加到ssh-agent中&#xff0c;为ssh client指定使用的秘钥文件 具体操作如下&#xff1a; 第一步&#xff1a;检查本地主机是否已经存在…

视频转webp批量处理工具哪个好?这里有答案

你是不是也遇到过这样的困扰&#xff1a;手机里存满了精彩的短视频&#xff0c;想做成动图分享到社交媒体&#xff0c;却发现转换后的GIF文件巨大无比&#xff0c;画质还惨不忍睹&#xff1f;要怎么把手机视频转webp&#xff0c;才能既保持高清画质&#xff0c;又能大幅减小文件…

【Fastjson】Fastjson2 在不同 Modules 模块包下,@JSONField name映射无法反序列化的 BUG 及解决

问题&#xff1a;在使用 alibaba fastjson2 做 JSONField 字段名映射时&#xff0c;在同模块包下 Flink Jar 任务正常映射&#xff0c;本地测试正常映射&#xff0c;但是将两个模块包上传至 Flink Cluster 之后&#xff0c;出现反序列化异常&#xff0c;子模块无法反序列化父模…

Go语言基础---数据类型间的故事

Go语言基础—数据类型间的故事 目录 前言基本数据类型 整形字节特殊整形unsafe.Sizeof数字字面量语法浮点型布尔值字符串byte和rune类型 运算符 算术运算符关系运算符逻辑运算符位运算符赋值运算符 前言 Go语言是Google开发的一种静态强类型、编译型语言。Go语言语法与C相近…

dedecms软件等级★号改成图片图标显示的办法

我们在用到dedecms织梦的软件模型&#xff0c;在调用软件星级的时候&#xff0c;要把默认的星号改为图片&#xff0c;这个要怎么操作呢&#xff1f;1、软件模型管理里面-字段管理-字段配置softrankislink一行改为&#xff1a;<field:softrank itemname软件等级 typeint isnu…

windows下安装claude code+国产大模型glm4.5接入(无需科学上网)

下载安装node.js https://nodejs.org/en/download 安装版.msi 直接下载安装即可 免安装版.zip 1.解压下载的压缩包 2.创建数据缓存存储目录cache和全局安装工具目录global 3.配置环境变量 【我的电脑】右键选中【属性】-> 找到【高级系统设置】-> 右下角【环境变量…

嵌入式 - ARM4

裸机实现LED闪烁一、启动代码1. 异常向量表配置1. .global汇编器指令&#xff0c;全局定义标签_start&#xff0c;作为汇编程序的默认起点2. 配置标签配置标签时可以前置加_ &#xff0c;以便和普通标签或系统标签做区分3. 异常向量表ARM架构规定异常向量表位置固定&#xff0c…

《C++ 108好库》之2 多线程库thread,mutex,condition_variable,this_thread

《C 108好库》之之2 多线程库thread&#xff0c;mutex&#xff0c;condition_variable&#xff0c;this_thread《C 108好库》之2 多线程库thread&#xff0c;mutex&#xff0c;condition_variable&#xff0c;this_threadstd::thread类​​互斥量&#xff08;Mutex&#xff09;…

Android系统框架知识系列(二十):专题延伸:JVM vs ART/Dalvik - Android运行时演进深度解析

​关键词​&#xff1a;运行时优化、AOT编译、JIT编译、内存管理、电池效率、性能分析一、Android运行时演进背景1. 移动环境的特殊挑战Android运行时环境的演进源于移动设备的独特限制&#xff1a;​移动设备约束条件​&#xff1a;​有限的内存资源​&#xff1a;早期设备仅1…

ubuntu 22 安装轻量级桌面Xfce并使用xrdp远程桌面连接

1.安装Xfce:sudo apt install xubuntu-desktop -y2.安装xrdp:sudo apt install xrdp -y3.配置xrdp&#xff0c;nano /etc/xrdp/xrdp.ini:[Globals] ... port3389 ; 远程连接端口&#xff0c;默认是3389&#xff0c;可以改成自己喜欢的端口... ; ; Session types ;; Some sess…

【Flask】测试平台开发,数据看板开发-第二十一篇

概述&#xff1a;在前面我们已经实现了我们的产品创建管理&#xff0c;应用管理管理&#xff0c;需求提测管理但是每周提测了多少需求&#xff0c;创建了哪些产品&#xff0c;我们是不是看着不是很直观&#xff0c;接下来我们就需要开发一个数据看板功能&#xff0c;实现能够看…

我是程序员,不是程序猿:请别把我当猴耍——拒绝被低估,用专业赢得尊重

摘要 本文旨在深度剖析“程序员”与“程序猿”一字之差背后所反映的职业尊严与身份认同问题。我们生活在一个技术驱动的时代&#xff0c;但对技术创造者的认知却常常被“程序猿”、“码农”等标签简单化、甚至矮化。本文将从正名开始&#xff0c;辨析“程序员”的专业内涵&…

C++中vector删除操作的安全隐患与最佳实践

std::vector 是C标准模板库&#xff08;STL&#xff09;中最常用的动态数组容器&#xff0c;提供了高效的随机访问和动态扩容能力。然而&#xff0c;其删除操作如果使用不当&#xff0c;会引入严重的安全隐患&#xff0c;包括未定义行为、内存泄漏和数据竞争等问题。本文将深入…

Unix/Linux 系统中的 `writev` 系统调用

<摘要> 本文对 Unix/Linux 系统中的 writev 系统调用进行了全面深入的解析。内容涵盖了其产生的背景&#xff08;从传统 write 的局限性到分散/聚集 I/O 概念的引入&#xff09;、核心概念&#xff08;如 struct iovec、系统调用流程&#xff09;。重点剖析了其设计意图&…