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

顺序表的实现(数据结构)——C语言

目录

1.结构与概念

2.分类

3 动态顺序表的实现

SeqList.h

SeqList.c

创建SLInit:

尾插SLPushBack以及SLCheak(检查空间是否足够):

头插SLPushFront:

尾删SLPopBack

头删SLPopFront

查找指定元素SLFind

指定位置插入SLInsert

指定位置删除SLEarse

打印元素SLPrint

销毁SLDestory

整体代码:

SeqList.h

SeqList.c


1.结构与概念

概念:顺序表是⽤⼀段物理地址连续的存储单元依次存储数据元素的线性结构,⼀般情况下采⽤数组存储。顺序表的底层其实就是顺序表,只是将数组进行了了一下包装。

2.分类

静态顺序表:使⽤定⻓数组存储元素;动态顺序表:空间不够用时,可以增加空间,静态顺序表缺陷:空间给少了不够⽤,给多了造成空间浪费,所以这里实现的是动态顺序表。

3 动态顺序表的实现

这里先还是创建三个文件,即test.c,SeqList.c,SeqList.h,分别是测试文件,顺序表的头文件,顺序表的函数实现文件,首先要在头文件中定义顺序表的结构体类型,结构体中有定义的数组类型,数据个数,以及空间大小,这里的数据类型DataType,在前面可以直接通过更改typedef后面直接修改整个的数据类型,这里以int类型为例:

typedef int DataType;typedef struct SeqList
{DataType* arr;int size ;int capacity ;
}SL;

还有就是头文件中肯定要包含各种头文件,这样在其他文件中直接包含“SeqList.h”就可以直接是用了,以及后面要实现的增删查改的操作的的函数头文件都包含在内:

SeqList.h

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>typedef int DataType;typedef struct SeqList
{DataType* arr;int size ;int capacity ;
}SL;void SLInit(SL* ps);
void SLDestroy(SL* ps);
void SLPrint(SL* ps);
void SLCheak(SL* ps);void SLPushback(SL* ps,DataType x);
void SLPushFront(SL* ps, DataType x);
void SLPopBack(SL* ps);
void SLPopFront(SL* ps);
void SLInsert(SL* ps, int pos,DataType x);
void SLErase(SL* ps, int pos);
int SLFind(SL* ps, DataType x);

SeqList.c

在这个文件中就是实现增删查改的各种函数,首先第一个为创建一个顺序表

创建SLInit:

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

初始情况下,数组指向空,空间大小,数据个数为0;还有注意这里要传一级指针,因为这里要使ps发生改变,后面的函数实现基本都要传一级指针;

尾插SLPushBack以及SLCheak(检查空间是否足够):

void SLCheak(SL* ps)
{if (ps->size == ps->capacity){int newcapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;DataType* tmp = (DataType*)realloc(ps->arr, newcapacity*sizeof(DataType));if (tmp == NULL){perror("realloc fail");exit(1);}ps->arr = tmp;ps->capacity = newcapacity;}
}void SLPushback(SL* ps, DataType x)
{assert(ps);SLCheak(ps);ps->arr[ps->size] = x;ps->size++;
}

因为这里实现插入操作,第一考虑的是,空间是否足够可以插入,所以这里实现了一个检查空间是否足够的函数SLCheak,如果空间够,就不进行任何操作,如果不够就要申请空间,申请空间每次为上次的两倍,如果是0的话,就附一个初值为4,申请空间时要判断是否申请成功,这里使用realloc函数,申请成功后再给ps;

尾差操作则是先判断ps是否为空后,直接在数组最后一个位置放入x,然后数据个数ps->size再++;

头插SLPushFront:

void SLPushFront(SL* ps, DataType x)
{assert(ps);SLCheak(ps);for (int i = ps->size; i > 0; i--){ps->arr[i] = ps->arr[i - 1];}ps->arr[0] = x;ps ->size++;
}

第一步任然是判断ps是否为空,以及空间大小是否足够,因为这里要在第一个位置插入,所以数组整体都要向后移动一位,这里就是一个for循环,为了避免数据被覆盖,从最后一个位置元素先向后移动再依次直到第一个元素被移到第二个位置结束,然后再插入元素x,ps->size再++;

尾删SLPopBack

void SLPopBack(SL* ps)
{assert(ps);assert(ps->size);ps->size--;
}

尾删即从最后删除一个元素,这里可以直接简单化处理,直接将ps->size--,这样就访问不到原本size-1位置的数据,相当于是把最后一个元素删掉了;

头删SLPopFront

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

头删即从第一个元素删除,这里可以直接将后面的元素依次先前移动一位,直接将第一个元素覆盖,这里要注意循环介质的条件,是ps->size-1,再将ps->size--即可;

查找指定元素SLFind

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

这里就是遍历数组,与x比较,找到就返回就行了;

指定位置插入SLInsert

void SLInsert(SL* ps, int pos, DataType x)
{assert(ps && pos < ps->size && pos >= 0);SLCheak(ps);for (int i = ps->size; i > pos; i--){ps->arr[i] = ps->arr[i - 1];}ps->arr[pos] = x;ps->size++;
}

这里和头插有点相似,这里主要注意结束循环是i>pos,就是将pos之后的元素向后移动一位,再在pos位置插入x,元素个数ps->size++;

指定位置删除SLEarse

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

和头删有异曲同工之妙,也是注意循环结束条件是ps->size-1,将pos之后的元素向前移动一位,然后元素个数ps->size--即可;

打印元素SLPrint

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

遍历数组,依次输出即可;

销毁SLDestory

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

将数组置为NULL,以及空间和元素个数都置为0;

整体代码:

SeqList.h

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>typedef int DataType;typedef struct SeqList
{DataType* arr;int size ;int capacity ;
}SL;void SLInit(SL* ps);
void SLDestroy(SL* ps);
void SLPrint(SL* ps);
void SLCheak(SL* ps);void SLPushback(SL* ps,DataType x);
void SLPushFront(SL* ps, DataType x);
void SLPopBack(SL* ps);
void SLPopFront(SL* ps);
void SLInsert(SL* ps, int pos,DataType x);
void SLErase(SL* ps, int pos);
int SLFind(SL* ps, DataType x);

SeqList.c

#include"SeqList.h"void SLInit(SL* ps)
{ps->arr = NULL;ps->size = 0;ps->capacity = 0;
}void SLDestroy(SL* ps)
{if (ps->arr != NULL){ps->arr = NULL;}ps->size = 0;ps->capacity = 0;
}void SLCheak(SL* ps)
{if (ps->size == ps->capacity){int newcapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;DataType* tmp = (DataType*)realloc(ps->arr, newcapacity*sizeof(DataType));if (tmp == NULL){perror("realloc fail");exit(1);}ps->arr = tmp;ps->capacity = newcapacity;}
}void SLPrint(SL* ps)
{assert(ps);for (int i = 0; i < ps->size; i++){printf("%d ", ps->arr[i]);}printf("\n");
}void SLPushback(SL* ps, DataType x)
{assert(ps);SLCheak(ps);ps->arr[ps->size] = x;ps->size++;
}void SLPushFront(SL* ps, DataType x)
{assert(ps);SLCheak(ps);for (int i = ps->size; i > 0; i--){ps->arr[i] = ps->arr[i - 1];}ps->arr[0] = x;ps ->size++;
}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--;
}void SLInsert(SL* ps, int pos, DataType x)
{assert(ps && pos < ps->size && pos >= 0);SLCheak(ps);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 && pos < ps->size && pos >= 0);for (int i = pos; i < ps->size - 1; i++){ps->arr[i] = ps->arr[i + 1];}ps->size--;
}int SLFind(SL* ps, DataType x)
{assert(ps);for (int i = 0; i < ps->size; i++){if (ps->arr[i] == x){return i;}}return -1;
}

相关文章:

顺序表的实现(数据结构)——C语言

目录 1.结构与概念 2.分类 3 动态顺序表的实现 SeqList.h SeqList.c 创建SLInit&#xff1a; 尾插SLPushBack以及SLCheak&#xff08;检查空间是否足够&#xff09;&#xff1a; 头插SLPushFront&#xff1a; 尾删SLPopBack 头删SLPopFront 查找指定元素SLFind 指定…...

【VUE】Vue中 computed计算属性和watch侦听器的区别

核心功能不同 computed 是一个计算属性&#xff0c;其核心功能是基于已有的数据属性计算得出新的属性值。当某个依赖的数据发生变化时&#xff0c;computed 会自动重新计算并更新自己的值。因此&#xff0c;可以将 computed 看做是一种“派生状态”。 watch 是一个观察者函数&…...

linux线程 | 同步与互斥 | 深度学习与理解同步

前言&#xff1a;本节内容主要讲解linux下的同步问题。 同步问题是保证数据安全的情况下&#xff0c;让我们的线程访问具有一定的顺序性。 线程安全就规定了它必须是在加锁的场景下的&#xff01;&#xff01;那么&#xff0c; 具体什么是同步问题&#xff0c; 我们加下来看看吧…...

Tkinter Frame布局笔记--做一个简易的计算器

#encodingutf-8 import tkinter import re import tkinter.messagebox import tkinter.simpledialog import sys import os def get_resources_path(relative_path):if getattr(sys,frozen, False):base_pathsys._MEIPASS#获取临时文件else:base_pathos.path.dirname(".&q…...

算法专题八: 链表

目录 链表1. 链表的常用技巧和操作总结2. 两数相加3. 两两交换链表中的节点4. 重排链表5. 合并K个升序链表6. K个一组翻转链表 链表 1. 链表的常用技巧和操作总结 常用技巧 画图!!! 更加直观形象, 便于我们理解引入虚拟头节点, 方便我们对链表的操作, 减少我们对边界情况的考…...

MySQL中关于NULL值的六大坑!你被坑过吗?

NULL值是我们在开发过程中的老朋友了&#xff0c;但是这个老朋友在MySQL中有很多坑&#xff0c;我通过这篇文章来总结分享一下&#xff0c;欢迎大家在评论区分享你的看法和踩坑经历。 1、NULL不等于NULL 在MySQL中&#xff0c;执行以下SQL会返回NULL 假如t表有以下数据&#…...

学生学习动机测试:激发潜能,引领未来

学习动机、学习兴趣和学习目标制定是影响学生学习成效的三个关键因素。通过对学生学习动机的测试,我们可以深入了解学生的学习状态,进而采取针对性的措施,激发他们的学习潜能,引导他们走向更加光明的未来。本文将从学习动机、学习兴趣和学习目标制定三个方面,详细探讨学生…...

基于SSM党务政务服务热线管理系统的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;用户管理&#xff0c;部门管理&#xff0c;办事信息管理&#xff0c;信息记录管理&#xff0c;系统管理 前台账号功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;部门&#xff0c;信息…...

OSI参考模型详解:初学者指南与实践案例

OSI参考模型详解&#xff1a;初学者指南与实践案例 OSI&#xff08;Open System Interconnect&#xff09;参考模型是一个由国际标准化组织&#xff08;ISO&#xff09;提出的七层网络分层模型&#xff0c;它为全球所有互联计算机系统提供了一个通用的通信框架&#xff0c;解决…...

S7-200 SMART 与 S7-1200 之间 TCP 通信— S7-200 SMART 作为服务器

TCP 协议通信 TCP 通信为面向连接的通信&#xff0c;需要双方都调用指令以建立连接及交换数据。S7-200 SMART 与 S7-1200 通过 TCP 通信&#xff0c;在 S7-1200 调用 T-block 指令 ( TCON, TDISCON, TSEND, TRCV ) &#xff0c;在 S7-200 SMART 调用 Open User Communication …...

Java @RequestPart注解:同时实现文件上传与JSON对象传参

RequestPart注解&#xff1a;用于处理multipart/form-data请求的一部分&#xff0c;通常用于文件上传或者处理表单中的字段。 java后端举例&#xff1a; PostMapping("/fileTest")public AjaxResult fileTest(RequestPart("file") MultipartFile file,Req…...

深度学习基础知识-02 数据预处理

深度学习的数据预处理通常包括&#xff1a; 1.数据清洗&#xff1a;去除错误或不完整的数据。 2.归一化&#xff1a;调整数据范围&#xff0c;如将像素值缩放到0-1。 3.数据增强&#xff1a;通过旋转、缩放等方法增加数据多样性。 4.数据划分&#xff1a;将数据分为训练集、验证…...

【CTF刷题9】2024.10.19

[MoeCTF 2021]babyRCE 考点&#xff1a;关键词过滤&#xff08;绕过方法参考往期博客&#xff09; 来源&#xff1a;nssctf <?php$rce $_GET[rce]; if (isset($rce)) {if (!preg_match("/cat|more|less|head|tac|tail|nl|od|vi|vim|sort|flag| |\;|[0-9]|\*|\|\%|\&g…...

WPF中的Setter

在 WPF (Windows Presentation Foundation) 中&#xff0c;Setter 是一个定义控件属性值的标记&#xff0c;通常用在 Style 或 Template 中。Setter 用于指定当某些条件满足时&#xff0c;控件的属性应该如何设置。以下是 Setter 的一些关键点&#xff1a; 属性设置&#xff1a…...

RabbitMQ下载与配置

安装Erlang Erlang 下载地址如下&#xff1a; https://erlang.org/download/otp_versions_tree.html 安装 RabbitMQ RabbitMQ 下载地址如下&#xff1a; https://www.rabbitmq.com/install-windows.html 查看服务&#xff0c;服务已经正常启动 打开Command Prompt 输入rabb…...

【数据结构与算法】力扣 54. 螺旋矩阵

问题描述 给你一个 m 行 n 列的矩阵 matrix &#xff0c;请按照 顺时针螺旋顺序 &#xff0c;返回矩阵中的所有元素。 示例 1&#xff1a; 输入&#xff1a; matrix [[1,2,3],[4,5,6],[7,8,9]] 输出&#xff1a; [1,2,3,6,9,8,7,4,5]示例 2&#xff1a; 输入&#xff1a; ma…...

速通不了的人工智能

下面是一个详细且系统的人工智能学习框架,涵盖了从基础理论到实际应用的各个方面。这个框架包括理论学习、编程实践、项目实战和资源推荐。为了帮助你更好地理解和应用,我会提供一些具体的代码示例。 人工智能学习框架 1. 基础理论 1.1 数学基础 线性代数:向量、矩阵、特…...

微信新功能上线,找工作也能“附近”搞定

大家好&#xff0c;我是小悟 你们听说了吗&#xff1f;微信又双叒叕出新功能啦&#xff01;这次可不是什么微整形、小游戏之类的小打小闹&#xff0c;而是实实在在的大招——查找附近的工作&#xff01;没错&#xff0c;你没听错&#xff0c;就是那个在你家门口就能找到工作的…...

CANoe与C#联合仿真方案

引言 CANoe作为一款强大的网络仿真工具,能够模拟各种通信协议,尤其是在汽车领域的CAN、LIN、Ethernet等协议。而C#作为一种广泛使用的编程语言,能够为CANoe提供灵活的用户界面和逻辑控制。本文将探讨如何将CANoe与C#结合,实现高效的联合仿真方案。 1. 系统架构 联合仿真…...

公交信息在线查询系统|基于java和小程序的公交信息在线查询系统小程序设计与实现(源码+数据库+文档)

公交信息在线查询系统小程序 目录 基于java和小程序的公交信息在线查询系统小程序设计与实现 一、前言 二、系统功能设计 三、系统实现 四、数据库设计 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八、源码获取&#xff1a; 博主介绍&#xff1a;✌️大厂…...

地震勘探——干扰波识别、井中地震时距曲线特点

目录 干扰波识别反射波地震勘探的干扰波 井中地震时距曲线特点 干扰波识别 有效波&#xff1a;可以用来解决所提出的地质任务的波&#xff1b;干扰波&#xff1a;所有妨碍辨认、追踪有效波的其他波。 地震勘探中&#xff0c;有效波和干扰波是相对的。例如&#xff0c;在反射波…...

进程地址空间(比特课总结)

一、进程地址空间 1. 环境变量 1 &#xff09;⽤户级环境变量与系统级环境变量 全局属性&#xff1a;环境变量具有全局属性&#xff0c;会被⼦进程继承。例如当bash启动⼦进程时&#xff0c;环 境变量会⾃动传递给⼦进程。 本地变量限制&#xff1a;本地变量只在当前进程(ba…...

定时器任务——若依源码分析

分析util包下面的工具类schedule utils&#xff1a; ScheduleUtils 是若依中用于与 Quartz 框架交互的工具类&#xff0c;封装了定时任务的 创建、更新、暂停、删除等核心逻辑。 createScheduleJob createScheduleJob 用于将任务注册到 Quartz&#xff0c;先构建任务的 JobD…...

Go 语言并发编程基础:无缓冲与有缓冲通道

在上一章节中&#xff0c;我们了解了 Channel 的基本用法。本章将重点分析 Go 中通道的两种类型 —— 无缓冲通道与有缓冲通道&#xff0c;它们在并发编程中各具特点和应用场景。 一、通道的基本分类 类型定义形式特点无缓冲通道make(chan T)发送和接收都必须准备好&#xff0…...

在树莓派上添加音频输入设备的几种方法

在树莓派上添加音频输入设备可以通过以下步骤完成&#xff0c;具体方法取决于设备类型&#xff08;如USB麦克风、3.5mm接口麦克风或HDMI音频输入&#xff09;。以下是详细指南&#xff1a; 1. 连接音频输入设备 USB麦克风/声卡&#xff1a;直接插入树莓派的USB接口。3.5mm麦克…...

WebRTC调研

WebRTC是什么&#xff0c;为什么&#xff0c;如何使用 WebRTC有什么优势 WebRTC Architecture Amazon KVS WebRTC 其它厂商WebRTC 海康门禁WebRTC 海康门禁其他界面整理 威视通WebRTC 局域网 Google浏览器 Microsoft Edge 公网 RTSP RTMP NVR ONVIF SIP SRT WebRTC协…...

数据库——redis

一、Redis 介绍 1. 概述 Redis&#xff08;Remote Dictionary Server&#xff09;是一个开源的、高性能的内存键值数据库系统&#xff0c;具有以下核心特点&#xff1a; 内存存储架构&#xff1a;数据主要存储在内存中&#xff0c;提供微秒级的读写响应 多数据结构支持&…...

js 设置3秒后执行

如何在JavaScript中延迟3秒执行操作 在JavaScript中&#xff0c;要设置一个操作在指定延迟后&#xff08;例如3秒&#xff09;执行&#xff0c;可以使用 setTimeout 函数。setTimeout 是JavaScript的核心计时器方法&#xff0c;它接受两个参数&#xff1a; 要执行的函数&…...

如何做好一份技术文档?从规划到实践的完整指南

如何做好一份技术文档&#xff1f;从规划到实践的完整指南 &#x1f31f; 嗨&#xff0c;我是IRpickstars&#xff01; &#x1f30c; 总有一行代码&#xff0c;能点亮万千星辰。 &#x1f50d; 在技术的宇宙中&#xff0c;我愿做永不停歇的探索者。 ✨ 用代码丈量世界&…...

基于Uniapp的HarmonyOS 5.0体育应用开发攻略

一、技术架构设计 1.混合开发框架选型 &#xff08;1&#xff09;使用Uniapp 3.8版本支持ArkTS编译 &#xff08;2&#xff09;通过uni-harmony插件调用原生能力 &#xff08;3&#xff09;分层架构设计&#xff1a; graph TDA[UI层] -->|Vue语法| B(Uniapp框架)B --&g…...