线性表之顺序表(增删查改)详解

news2025/1/11 16:46:54

🍕博客主页:️自信不孤单

🍬文章专栏:数据结构与算法

🍚代码仓库:破浪晓梦

🍭欢迎关注:欢迎大家点赞收藏+关注

文章目录

  • 🍉线性表
  • 🍒顺序表
    • 1. 概念及结构
    • 2. 接口实现
      • 2.1 初始化顺序表
      • 2.2 销毁顺序表
      • 2.3 检查顺序表容量
      • 2.4 顺序表尾插
      • 2.5 顺序表尾删
      • 2.6 顺序表头插
      • 2.7 顺序表头删
      • 2.8 打印顺序表
      • 2.9 查找指定值
      • 2.10 在指定下标位置插入数据
      • 2.11 删除指定下标位置的数据
      • 2.12 修改指定下标位置的数据
    • 3. 接口测试


🍉线性表

  • 线性表(linear list)是n个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使用的数据结构,常见的线性表:顺序表、链表、栈、队列、字符串…

  • 线性表在逻辑上是线性结构,也就是连续的一条直线。但是在物理结构上并不一定是连续的,线性表在物理上存储时,通常以数组和链式结构的形式存储。

    补充

    • 逻辑结构:数据元素之间的逻辑关系,即人对数据的理解,而进行抽象的模型。
    • 物理结构 :数据元素在计算机中的存储方法,即计算机对数据的理解,逻辑结构在计算机语言中的映射。

在这里插入图片描述

🍒顺序表

1. 概念及结构

概念

顺序表是在计算机内存中以数组的形式保存的线性表,线性表的顺序存储是指用一组地址连续的存储单元依次存储线性表中的各个元素、使得线性表中在逻辑结构上相邻的数据元素存储在相邻的物理存储单元中,即通过数据元素物理存储的相邻关系来反映数据元素之间逻辑上的相邻关系,采用顺序存储结构的线性表通常称为顺序表。

结构

顺序表一般可以分为:

  1. 静态顺序表:使用定长数组存储元素。
#define N 10
typedef int SLDataType;
												
typedef struct SeqList
{
	SLDataType array[N];  //定长数组
	size_t size;          //有效数据个数
}SeqList;

在这里插入图片描述

  1. 动态顺序表:使用动态开辟的数组存储。
typedef int SLDataType; //类型重命名,后续要存储其它类型时方便更改
												
typedef struct SeqList
{
	SLDataType* a;    //指向动态开辟的数组
	size_t size;      //有效数据个数
	size_t capacity;  //容量大小
}SeqList;

在这里插入图片描述

2. 接口实现

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

首先创建两个文件实现动态顺序表:

  • SeqList.h(顺序表的类型声明、接口函数声明、头文件的包含)
  • SeqList.c(顺序表接口函数的实现)

接着创建 test.c 文件来测试各个接口

如图:

在这里插入图片描述

SeqList.h 文件内容如下:

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

typedef int SLDataType;
typedef struct SeqList
{
	SLDataType* a;
	int size;
	int capacity;
}SeqList;

// 对数据的管理:增删查改 
void SeqListInit(SeqList* ps);
void SeqListDestroy(SeqList* ps);

void SeqListPrint(SeqList* ps);
void SeqListPushBack(SeqList* ps, SLDataType x);
void SeqListPushFront(SeqList* ps, SLDataType x);
void SeqListPopFront(SeqList* ps);
void SeqListPopBack(SeqList* ps);

// 顺序表查找
int SeqListFind(SeqList* ps, SLDataType x);
// 顺序表在pos位置插入x
void SeqListInsert(SeqList* ps, int pos, SLDataType x);
// 顺序表删除pos位置的值
void SeqListErase(SeqList* ps, int pos);
//修改pos位置的值为x
void SeqListModify(SeqList* ps, int pos, SLDataType x);

接下来,我们在 SeqList.c 文件中实现各个接口函数。

2.1 初始化顺序表

初始化开辟5个数据的空间。

void SeqListInit(SeqList* ps)
{
	assert(ps);
	ps->a = (SLDataType*)malloc(sizeof(SLDataType) * 5);
	if (ps->a == NULL)
	{
		perror("malloc fail");
		return;
	}
	ps->capacity = 5;
	ps->size = 0;
}

2.2 销毁顺序表

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

2.3 检查顺序表容量

若顺序表已满,则扩容为原容量的2倍。

void CheckCapacity(SeqList* ps)
{
	assert(ps);
	if (ps->size == ps->capacity)
	{
		SLDataType* tmp = (SLDataType*)realloc(ps->a, sizeof(SLDataType) * ps->capacity * 2);
		if (tmp == NULL)
		{
			perror("reallo fail");
			return;
		}
		ps->a = tmp;
		ps->capacity *= 2;
	}
}

2.4 顺序表尾插

注意检查容量。

void SeqListPushBack(SeqList* ps, SLDataType x)
{
	assert(ps);
	CheckCapacity(ps);
	ps->a[ps->size] = x;
	ps->size++;
}

2.5 顺序表尾删

注意原数据个数要大于0,才可执行删除操作。

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

2.6 顺序表头插

所有数据依次向后挪动一个数据的位置,再将要插入的数据放在第一位。
注意挪动要从后往前进行,防止有效数据覆盖。

void SeqListPushFront(SeqList* ps, SLDataType x)
{
	assert(ps);
	CheckCapacity(ps);
	for (int i = ps->size; i >= 1; i--)
	{
		ps->a[i] = ps->a[i - 1];
	}
	ps->a[0] = x;
	ps->size++;
}

2.7 顺序表头删

判断原数据个数要大于0,才可执行删除操作。
从第二位开始依次向前挪动一个数据的位置,将第一个数据覆盖。
注意挪动要从前往后进行,防止有效数据覆盖。

void SeqListPopFront(SeqList* ps)
{
	assert(ps);
	assert(ps->size > 0);
	for (int i = 0; i < ps->size - 1; i++)
	{
		ps->a[i] = ps->a[i+1];
	}
	ps->size--;
}

2.8 打印顺序表

void SeqListPrint(SeqList* ps)
{
	assert(ps);
	for (int i = 0; i < ps->size; i++)
	{
		printf("%d ", ps->a[i]);
	}
	printf("\n");
}

2.9 查找指定值

找到返回指定值的下标,否则返回-1。

int SeqListFind(SeqList* ps, SLDataType x)
{
	assert(ps);
	for (int i = 0; i < ps->size; i++)
	{
		if (ps->a[i] == x)
		{
			return i;
		}
	}
	return -1;
}

2.10 在指定下标位置插入数据

首先需判断插入的位置是否越界。
然后检查容量。
从指定位置开始依次向后挪动一个数据,再将要插入的数据放在指定的位置上。
注意挪动要从后往前进行,防止有效数据覆盖。

void SeqListInsert(SeqList* ps, int pos, SLDataType x)
{
	assert(ps);
	assert(pos >= 0 && pos <= ps->size);
	CheckCapacity(ps);
	for (int i = ps->size; i > pos; i--)
	{
		ps->a[i] = ps->a[i - 1];
	}
	ps->a[pos] = x;
	ps->size++;
}

2.11 删除指定下标位置的数据

判断原数据个数要大于0,才可执行删除操作。
从第指定位置开始依次向前挪动一个数据的位置,将指定位置数据覆盖。
注意挪动要从前往后进行,防止有效数据覆盖。

void SeqListErase(SeqList* ps, int pos)
{
	assert(ps);
	assert(pos >= 0 && pos < ps->size);
	for (int i = pos; i < ps->size - 1; i++)
	{
		ps->a[i] = ps->a[i + 1];
	}
	ps->size--;
}

2.12 修改指定下标位置的数据

void SeqListModify(SeqList* ps, int pos, SLDataType x)
{
	assert(ps);
	assert(pos >= 0 && pos < ps->size);
	ps->a[pos] = x;
}

注:在每个接口函数中一定要使用assert函数断言防止对空指针的引用。

补充对于越界的理解:

越界不一定报错,系统对越界的检查是一种抽查。

  • 越界读一般是检查不出来的。
  • 越界写如果是修改到标志位才会检查出来。(系统在数组末尾后设有标志位,越界写时,恰好修改到标志位了,就会被检查出来)

3. 接口测试

test.c 文件内容如下:

#define _CRT_SECURE_NO_WARNINGS 1

#include "SeqList.h"

void test()
{
	//创建顺序表
	SeqList sl;
	//初始化
	SeqListInit(&sl);
	//尾插
	SeqListPushBack(&sl, 5);
	SeqListPrint(&sl);
	//头插
	SeqListPushFront(&sl, 1);
	SeqListPrint(&sl);
	SeqListPushFront(&sl, 0);
	SeqListPrint(&sl);
	//尾插
	SeqListPushBack(&sl, 6);
	SeqListPrint(&sl);
	//指定插
	SeqListInsert(&sl, 2, 2);
	SeqListPrint(&sl);
	SeqListInsert(&sl, 3, 3);
	SeqListPrint(&sl);
	SeqListInsert(&sl, 4, 4);
	SeqListPrint(&sl);
	//查找
	int n = SeqListFind(&sl, 4);
	printf("查找数据4的下标为:>%d\n", n);
	//尾删
	SeqListPopBack(&sl);
	SeqListPrint(&sl);
	//头删
	SeqListPopFront(&sl);
	SeqListPrint(&sl);
	//指定删
	SeqListErase(&sl, 3);
	SeqListPrint(&sl);
	//修改位置3的数据为4
	SeqListModify(&sl, 3, 4);
	SeqListPrint(&sl);
	//销毁顺序表
	SeqListDestroy(&sl);
}

int main()
{
	test();
	return 0;
}

运行结果:

在这里插入图片描述


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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

数据库JDBC

数据库厂商提供一个程序来完成 API 的转换&#xff0c;对原生 API 封装再提供成JDBC 的形状。 这个程序叫数据库驱动包。 JAVA程序员要想对数据库开发&#xff0c; 就要导入对应的数据库驱动包&#xff0c;才能编写代码。 数据库驱动是让JDBC认识数据库API URL 计算机里的一…

MySQL安装与新用户的创建相关

一、MySQL安装 1. 官网下载mysql的ims包 MySQL :: Download MySQL Installer (Archived Versions) 下载好&#xff0c;双击运行。 2. 根据提示进行安装 这里选择手动安装的选项&#xff1a; 然后选择你安装的MySQL版本&#xff0c;这里是5.7 勾选自定义MySQL安装位置 下一…

教育大数据总体解决方案(7)

考勤查询 创客教室 为体现学校创新教育的成果&#xff0c;丰富学校创新实践活动&#xff0c;加强创新课程普及教育&#xff0c;把机器人创新教育作为学校的教育特色来体现&#xff0c;使学生通过理论与实践相结合的方法&#xff0c;进一步学习掌握机械、电子结构、信息技术、人…

让我们谈谈你对 ThreadLocal 的理解

介绍 ThreadLocal 从 JDK1.2 开始&#xff0c;ThreadLocal 是一个被用来存储线程本地变量的类。在 ThreadLocal 中的变量在线程之间是独立的。当多个线程访问 ThreadLocal 中的变量&#xff0c;它们事实上访问的是自己当前线程在内存中的变量&#xff0c;这能确保这些变量是线…

基于鲸鱼算法的极限学习机(ELM)回归预测-附代码

基于鲸鱼算法的极限学习机(ELM)回归预测 文章目录 基于鲸鱼算法的极限学习机(ELM)回归预测1.极限学习机原理概述2.ELM学习算法3.回归问题数据处理4.基于鲸鱼算法优化的ELM5.测试结果6.参考文献7.Matlab代码 摘要&#xff1a;本文利用鲸鱼算法对极限学习机进行优化&#xff0c;并…

kettle——数据清洗(数据表——>转换——>数据表)

目录 1、表输入 ①点击“新建”选项&#xff0c;新建数据库 ②选择“获取SQL” ③选择表a ④注意&#xff1a;字段只显示了5个&#xff0c;而一共有6个字段&#xff0c;money字段需要手动添加 2、转换 ①打开java 控件&#xff0c;设置变量 3、表输出 ①连接表b ②映…

【Redis7】Redis7 复制(重点:复制原理)

【大家好&#xff0c;我是爱干饭的猿&#xff0c;本文重点介绍Redis7 复制。 后续会继续分享Redis7和其他重要知识点总结&#xff0c;如果喜欢这篇文章&#xff0c;点个赞&#x1f44d;&#xff0c;关注一下吧】 上一篇文章&#xff1a;《【Redis7】Redis7 事务&管道&…

Git入门指南(手把手教学)

Git入门指南 一、什么是Git二、Git的安装下载三、git的简单实践1.创建git仓库2.Windows上生成公钥以绑定GitHub仓库3.写一个Helloworld 四、帮助学习的网站 一、什么是Git Git是一种分布式版本控制系统&#xff0c;它是由Linus Torvalds为了管理Linux内核开发而开发的。与中心化…

项目第四天

解决了路变墙 墙变路的问题 void onechange(ExMessage* msg) {if (msg->message WM_LBUTTONDOWN && msg->x > 50 && msg->x < 410 && msg->y > 50 && msg->y < 410){//printf("鼠标位置&#xff1a;x&#…

Vue.js中class与style的增强绑定

目录 一、v-bind绑定class属性 &#xff08;1&#xff09;绑定class样式&#xff0c;字符串写法 &#xff08;2&#xff09;绑定class样式&#xff0c;数组写法 &#xff08;3&#xff09;绑定class样式&#xff0c;对象写法 二、v-bind绑定内联样式style &#xff08;1&…

【CSS3】CSS3 属性选择器 ( CSS3 简介 | 属性选择器 | 属性选择器权重 )

文章目录 一、CSS3 简介二、CSS3 属性选择器权重三、CSS3 属性选择器 一、CSS3 简介 CSS3 是在 CSS2 基础上进行扩展后的样式 ; 在 移动端 对 CSS3 的支持 要比 PC 端支持的更好 , 建议在移动端开发时 , 多使用 CSS3 ; PC 端老版本浏览器不支持 CSS3 , 尤其是 IE 9 及以下的版…

【Linux 裸机篇(五)】I.MX6ULL BSP工程管理下的 Makefile编写、链接脚本

目录 一、BSP 工程二、Makefile三、链接脚本 一、BSP 工程 文件夹描述bsp存放驱动文件imx6ul存放跟芯片有关的文件&#xff0c;比如 NXP 官方的 SDK库文件obj存放编译生成的.o 文件project存放 start.S 和 main.c 文件&#xff0c;也就是应用文件 二、Makefile 1 CROSS_COMPI…

ESP32设备驱动-BMA400加速度传感器驱动

BMA400加速度传感器驱动 文章目录 BMA400加速度传感器驱动1、BMA400介绍2、硬件准备3、软件准备4、驱动实现1、BMA400介绍 BMA400 是第一款真正的超低功耗加速度传感器,不会影响性能。 BMA400 具有 12 位数字分辨率、连续测量和定义的可选带宽以及超低功耗,允许对三个垂直轴…

带有时钟使能和同步清零的D触发器

每个 Slice 有 8 个 FF 。四个可以配置为 D 型触发器或电平敏感锁存器&#xff0c;另外四个只能配置为 D 型触发器&#xff0c;但是需要记得是&#xff1a;当原来的四个 FF 配置为锁存器时&#xff0c;不能使用这四个 FF 。 &#xff08;1&#xff09;FDCE 简介 带有时钟使能…

【grpc01】入门

目录 背景 单体架构 微服务架构 代码冗余问题 服务之间调用 grpc protobuf protoc protoc-gen-go 背景 单体架构 有一些致命缺点&#xff1a; 一旦某个服务宕机&#xff0c;会引起整个应用不可用&#xff0c;隔离性差只能整体应用进行伸缩&#xff0c;浪费资源&#…

【Java基础】迷宫问题的Java代码实现

迷宫问题通常是指在给定的迷宫中&#xff0c;找到从起点到终点的路径的问题。迷宫通常由障碍物和自由空间组成&#xff0c;其中障碍物是不可穿越的区域&#xff0c;自由空间可以穿越。解决迷宫问题的方法有很多种&#xff0c;本文使用递归算法来解决迷宫问题。 一、使用递归算法…

MATLAB简单图形绘制(五)

目录 实验目的 实验内容 实验目的 1&#xff09;掌握MATLAB图形绘制的基本原理和方法&#xff1b; 2&#xff09;熟悉和了解MATLAB图形绘制程序编辑的基本指令&#xff1b; 3&#xff09;掌握利用MATLAB图形编辑窗口编辑和修改图形界面&#xff0c;并添加图形的各种标注&…

人工智能技术在软件开发中的应用

人工智能技术的不断发展和成熟&#xff0c;使得它在软件开发中的应用越来越广泛。人工智能技术的应用可以帮助软件开发人员提高效率、降低成本、增强软件的功能性和可靠性。在本文中&#xff0c;我们将探讨人工智能技术在软件开发中的应用&#xff0c;并且提供一些实际案例&…

借助高性能计算的发展十大网络趋势

当今的网络支持复杂企业IT环境中的大量工作负载。而借助高性能计算(HPC)和人工智能/深度学习的应用程序&#xff0c;企业可以满足对更快计算周期、更高数据传输率和出色连接性日益增长的需求。 当今的网络支持复杂企业IT环境中的大量工作负载。而借助高性能计算(HPC)和人工智能…

比spire.pdf速度更快:EVO PDF Print Crack

适用于 .NET 的 EVO PDF 打印 EVO PDF Print 可用于任何类型的 .NET 应用程序&#xff0c;以静默打印 PDF 文档而不显示任何打印对话框。它可以集成到任何 .NET 应用程序中&#xff0c;包括 ASP.NET 网站和桌面应用程序&#xff0c;以便为您的应用程序添加 PDF 打印功能。您可以…