顺序表各种接口的实现(C)

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

概念

  • 用一段物理地址连续的存储单元
  • 依次存储数据元素的线性结构,一般情况下采用数组存储。
  • 在数组上完成数据的增删查改
    一般可以分为
  1. 静态顺序表:使用定长数组存储元素
#define N 1000
typedef int SLDataType;

typedef struct SeqList    //对类型进行重命名,方便后续变换类型
{
	SLDataType array[N];  //定长数组
	size_t size;          //有效数据个数
}SL;
  1. 动态顺序表:使用动态开辟的数组存储
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>

typedef int SLDataType;

typedef struct SeqList
{
	SLDataType* array;  //指向动态开辟的数组
	size_t size;        //有效数据个数
	size_t capacity;    //容量空间的大小
}SL;

![[Pasted image 20240810054754.png]]

初始化
  • 每次调用接口,要判断传入的指针是不是空指针
void SLInit(SL* ps)
{
	assert(ps);
	
	ps->a = (SLDataType*)malloc(sizeof(SLDataType)*4);
	if (ps->a == NULL)
	{
		perror("malloc failed");
		exit(-1);         //程序直接在这里结束
	}
	
	ps->size = 0;
	ps->capacity = 0;
}
  • 动态内存,用malloc开辟空间,先开4个
  • 检查malloc出的地址是否为空指针
  • 将size和capacity初始化为0
销毁
void SLDestroy(SL* ps)
{
	assert(ps);

	free(ps-> a);
	ps->a = NULL;
	ps->capacity = ps->size = 0;
}
  • 直接释放掉malloc的空间,将a指针置为NULL
  • 将size和capacity置为0
打印
void SLPrint(SL* ps)
{
	assert(ps);
	
	for (int i = 0; i < ps-> size; i++)
	{
		printf("%d ", ps->a[i]);
	}
	printf("\n");
}
  • 从下标0开始往右遍历,直到最后一个元素,即size-1
扩容
void SLCheckCapacity(SL* ps)
{
	assert(ps);
	
	if (ps->size == ps->capacity)
	{
		SLDataType* tmp = (SLDataType*)realloc(ps->a, ps->capacity * 2 * (sizeof(SLDataType)));
		if (tmp == NULL)
		{
			perror("realloc failed");
			exit(-1);
		}

		ps->a = tmp;
		ps->capacity *= 2;
	}
}
  • 当size等于capacity时,realloc,重新开辟空间,一般扩2倍容量
尾插
void SLPushBack(SL* ps, SLDataType x)
{
	assert(ps);
	
	if (ps->size == ps->capacity)
	{
		SLDataType* tmp = (SLDataType*)realloc(ps->a, ps->capacity * 2 * (sizeof(SLDataType)));
		if (tmp == NULL)
		{
			perror("realloc failed");
			exit(-1);
		}

		ps->a = tmp;
		ps->capacity *= 2;
	}

	ps->a[ps->size] = x;
	ps->size++;
}
  • 在下标size处插入值,size++,如果size等于capacity,就扩容
尾删
void SLPopBack(SL* ps)
{
	assert(ps);
	
	//if (ps->size == 0)
	//	return;
	assert(ps->size > 0);
	
	ps->size--;
}
  • 直接size–,覆盖掉尾部的元素
  • 断言size,size不能减为负数
头插
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++;
}

需要整体元素往右挪动
而且只能从右往左开始遍历,反过来会覆盖没有处理的元素

end从size-1开始
![[Pasted image 20240810060526.png]]

把当前元素往右移动一格,传给end+1
![[Pasted image 20240810061642.png]]

end–,往前一格
![[Pasted image 20240810060703.png]]

直到end=0
![[Pasted image 20240810060808.png]]

把x传进来,size++
![[Pasted image 20240810060931.png]]

当size=capacity时,就需要扩容

头删
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--;
}

从左往右,挨个往左移动
begin从下标1开始
![[Pasted image 20240810061444.png]]

把begin的内容覆盖给begin-1
![[Pasted image 20240810062211.png]]

begin++
![[Pasted image 20240810061551.png]]

直到begin=size-1
![[Pasted image 20240810062002.png]]

size–
![[Pasted image 20240810062046.png]]

查找
int SLFind(SL* ps, SLDataType x)
{
	assert(ps);
	
	for (int i = 0; i < ps->size; i++)
	{
		if (ps->a[i] == x)
		{
			return i;
		}
	}

	return -1;
}
  • 依次遍历每个元素,找到以后,返回下标,否则返回-1
插入
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++;
}
  • 先判断pos是否合法,pos可以等于size,因为可以尾插
    end从size-1开始
    ![[Pasted image 20240810064522.png]]

当end大于等于pos时,end开始循环
将end传给end+1
![[Pasted image 20240810064811.png]]

end–,往左移动
![[Pasted image 20240810064743.png]]

直到end=pos
![[Pasted image 20240810064858.png]]

将x传给pos,size++
![[Pasted image 20240810064941.png]]

当pos直接等于size时,相当于尾插
等于0时,相当于头插

删除
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--;
}
  • 同样判断pos是否合法
    begin从pos+1开始
    ![[Pasted image 20240810065127.png]]

将begin传给begin-1
![[Pasted image 20240810065200.png]]

begin++
![[Pasted image 20240810065219.png]]

直到begin=size-1
![[Pasted image 20240810065252.png]]

size–
![[Pasted image 20240810065322.png]]

当pos等于size-1时,相当于尾删
等于0时,相等于头删

修改
void SLModify(SL* ps, int pos, SLDataType x)
{
	assert(ps);
	
	assert(pos >= 0 && pos < ps->size);
	
	ps->a[pos] = x;
}
  • 判断pos的合法性,直接通过数组下标修改

声明定义分离实现

//管理数据 -- 增删查改
//初始化
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);
//查找
int SLFind(SL* ps, SLDataType x);
//插入
void SLInsert(SL* ps, int pos, SLDataType x);
//删除
void SLErase(SL* ps, int pos);
//修改
void SLModify(SL* ps, int pos, SLDataType x);
#include "SeqList.h"

void SLInit(SL* ps)
{
	assert(ps);
	
	ps->a = (SLDataType*)malloc(sizeof(SLDataType)*4);
	if (ps->a == NULL)
	{
		perror("malloc failed");
		exit(-1);         //程序直接在这里结束
	}
	
	ps->size = 0;
	ps->capacity = 0;
}

void SLDestroy(SL* ps)
{
	assert(ps);

	free(ps-> a);
	ps->a = NULL;
	ps->capacity = ps->size = 0;
}

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

void SLCheckCapacity(SL* ps)
{
	assert(ps);
	
	if (ps->size == ps->capacity)
	{
		SLDataType* tmp = (SLDataType*)realloc(ps->a, ps->capacity * 2 * (sizeof(SLDataType)));
		if (tmp == NULL)
		{
			perror("realloc failed");
			exit(-1);
		}

		ps->a = tmp;
		ps->capacity *= 2;
	}
}

void SLPushBack(SL* ps, SLDataType x)
{
	assert(ps);
	
	if (ps->size == ps->capacity)
	{
		SLDataType* tmp = (SLDataType*)realloc(ps->a, ps->capacity * 2 * (sizeof(SLDataType)));
		if (tmp == NULL)
		{
			perror("realloc failed");
			exit(-1);
		}

		ps->a = tmp;
		ps->capacity *= 2;
	}

	ps->a[ps->size] = x;
	ps->size++;
}

void SLPopBack(SL* ps)
{
	assert(ps);
	
	//if (ps->size == 0)
	//	return;
	assert(ps->size > 0);
	
	ps->size--;
}

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++;
}

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--;
}

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

	return -1;
}

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++;
}

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--;
}

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

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

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

相关文章

Qt 小功能:加载等待动画——转圈圈

加载等待动画实现——转圈圈 效果图&#xff1a;&#xff08;看封面最好&#xff09; 关键要点 流畅的动画&#xff1a; 使用 QTimer 每 50 毫秒更新一次动画&#xff0c;确保动画流畅。 视觉效果&#xff1a; 使用 QPainter 的平滑像素转换和抗锯齿选项&#xff0c;提高动画…

DHU OJ 循环结构 回文数字

思路及代码&#xff1a; 由于只考虑5位和6位回文数&#xff0c;3个 for 循环次数为9*10*10还可以&#xff0c;就直接遍历了 //input n int 10< <100 #include<iostream> using namespace std; int main(){int n;cin >> n;int ans 0; //solution //判断是…

HTML 元素提供的附加信息--属性 ——WEB开发系列03

HTML 属性是指用于描述 HTML 元素的额外信息&#xff0c;它们提供了元素的特定配置或行为&#xff0c;属性通常包含在 HTML 元素的开始标签中。 元素也可以拥有属性&#xff0c;属性看起来像这样&#xff1a; 属性是元素的附加信息&#xff0c;它们不会显示在实际内容中。在前述…

适合初学者的2024年数据恢复软件指南

现在大家应该经常会将数据存储在一些存储设备里。但这些设备可能会因为各种原因导致数据意外的丢失&#xff0c;这时候如果我们掌握了全免费的数据恢复工具的使用方式&#xff0c;就可以尽可能的避免数据丢失的情况。 1.福晰数据恢复 连接直达&#xff1a;https://www.pdf365…

跑腿代购app系统源码开发及功能分析

随着互联网技术的飞速发展和人们生活节奏的加快&#xff0c;跑腿代购服务作为一种便捷的生活方式&#xff0c;正逐渐渗透到我们日常生活的方方面面。从日常购物、餐饮外卖到文件传递、药品代购&#xff0c;跑腿服务以其高效、灵活的特点赢得了广大用户的青睐。而支撑这一服务高…

多进程架构关键技术之FileMapping技术应用

1. 前言 在多进程架构设计中&#xff0c;使用FileMapping技术是一种关键的技术选择。它能够显著提升多进程间数据共享和通信的效率&#xff0c;同时简化了复杂的进程间数据交互和同步管理。以下是FileMapping技术在多进程架构设计中的应用及其关键优势&#xff1a; 2. 共享数…

Linux项目自动构建工具 make/makefile

目录 0.前言 1.make/makefile是什么 2.makefile的语法 2.1基本语法 2.2依赖关系 2.3. 示例&#xff1a;一个简单的C程序 3.使用指令自动构建与清除 3.1自动构建 3.2自动清除 3.3自动化工作流 3.4扩展&#xff1a;更多伪目标 4.make的工作原理 5.使用make/makefile的优势 6.小结…

高质量WordPress下载站模板5play主题源码

5play下载站是由国外站长开发的一款WordPress主题&#xff0c;主题简约大方&#xff0c;为v1.8版本&#xff0c; 该主题模板中包含了上千个应用&#xff0c;登录后台以后只需要简单的三个步骤就可以轻松发布apk文章&#xff0c; 我们只需要在WordPress后台中导入该主题就可以…

Spring配置

1.Spring的两大核心思想IOC和AOP思想 1.1类注解 1.Controller, Service, Configuration, Component, Repository 1.2方法注解 bean&#xff08;这个方法搭配上面的五大注解进行使用&#xff09; 2.Bean的名称 2.1.类注解名称 &#xff08;1&#xff09;默认首字母小写驼…

数组结构:链式结构二叉树

1.实现链式结构二叉树 用链表来表示一棵二叉树&#xff0c;即用链来指示元素的逻辑关系。通常的方法是链表中每个结点由三个域组成&#xff0c;数据域和左右指针域&#xff0c;左右指针分别用来给结点的左孩子和右孩子所在的链结点的存储地址&#xff0c;其结构如下&#xff1…

Micrometer Tracing和Zipkin实现链路追踪

一、为什么使用链路追踪 在微服务框架中&#xff0c;一个由客户端发起的请求在后端系统中会经过多个不同的的服务节点调用来协同产生最后的请求结果&#xff0c;每一个前段请求都会形成一条复杂的分布式服务调用链路&#xff0c;链路中的任何一环出现高延时或错误都会引起整个…

【经验分享】ShardingSphere+Springboot-03 : COMPLEX_INLINE 复杂行表达式分片算法

文章目录 3.3 复杂分片算法3.3.1 COMPLEX_INLINE 复杂行表达式分片算法 3.3 复杂分片算法 3.3.1 COMPLEX_INLINE 复杂行表达式分片算法 复合分片比较灵活&#xff0c;适合于分片的字段比较多&#xff0c;分片比较复杂的场景&#xff0c;使用这种分片的话必须对自己的业务比较…

深度学习——神经网络(neural network)详解(二). 带手算步骤,步骤清晰0基础可看

深度学习——神经网络&#xff08;neural network&#xff09;详解&#xff08;二&#xff09;. 手算步骤&#xff0c;步骤清晰0基础可看 前文如下&#xff1a;深度学习——神经网络&#xff08;neural network&#xff09;详解&#xff08;一&#xff09;. 带手算步骤&#x…

Java面试篇(JVM相关专题)

文章目录 0. 前言1. 为什么要学 JVM2. 什么是 JVM3. JVM 的好处3.1 一次编写&#xff0c;到处运行3.2 自动内存管理&#xff08;基于垃圾回收机制&#xff09; 4. 要学习哪些 JVM 的哪些内容5. JVM 的组成5.1 程序计数器5.2 堆5.3 什么是虚拟机栈常见问题一&#xff1a;垃圾回收…

代码+视频,R语言VRPM绘制多种模型的彩色列线图

列线图&#xff0c;又称诺莫图&#xff08;Nomogram&#xff09;&#xff0c;它是建立在回归分析的基础上&#xff0c;使用多个临床指标或者生物属性&#xff0c;然后采用带有分数高低的线段&#xff0c;从而达到设置的目的&#xff1a;基于多个变量的值预测一定的临床结局或者…

机器学习入门篇之监督学习(回归篇)——多元线性回归的原理介绍

在机器学习入门之监督学习&#xff08;分类篇&#xff09;-CSDN博客&#xff0c;以及初步接触了机器学习&#xff0c;在这片文章中我们继续沿着思维导图学习监督学习的剩下部分&#xff0c;回归。 在监督学习中&#xff0c;回归是一种预测型建模技术&#xff0c;它涉及预测一个…

尚硅谷谷粒商城项目笔记——十、调试前端项目renren-fast-vue【电脑CPU:AMD】

十、调试前端项目renren-fast-vue 如果遇到其他问题发在评论区&#xff0c;我看到后解决 1 先下载安装git git官网下载地址 2 登录gitee搜索人人开源找到renren-fast-vue复制下载链接。【网课视频中也有详细步骤】 3 下载完成后桌面会出现renren-fast-vue的文件夹 4 开始调…

【阿旭机器学习实战】【39】脑肿瘤数据分析与预测案例:数据分析、预处理、模型训练预测、评估

《------往期经典推荐------》 一、【100个深度学习实战项目】【链接】&#xff0c;持续更新~~ 二、机器学习实战专栏【链接】&#xff0c;已更新31期&#xff0c;欢迎关注&#xff0c;持续更新中~~ 三、深度学习【Pytorch】专栏【链接】 四、【Stable Diffusion绘画系列】专…

python如何判断中文是否一致

Python判断两个相等的中文字符串为false&#xff0c;将两个待比较的字符串都把unicode编码设为‘utf-8’也不能解决问题&#xff0c;具体原因如下&#xff1a; 1、首先查看待比较两个字符串的编码格式 &#xff0c;使用命令&#xff1a; import chardet ...... string_code c…

macos重装系统 启动U盘制作方法 - createinstallmedia 命令使用方法总结

macos重装系统比windows要稍微复杂一些&#xff0c;不过还好&#xff0c;macos系统安装app这个Apple官方提供的系统软件里面默认就内置了一个可用为我们制作启动盘的工具 createinstallmedia 我们下载的apple安装镜像要门是 dmg/pkg/iso 的压缩档案格式的&#xff0c;要么是 x…