数据结构初阶(C语言)-顺序表

一,线性表

在进行顺序表的介绍之前,我们先来了解下什么是线性表:

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

二,顺序表

2.1概念与其逻辑及物理结构

         概念:顺序表是用⼀段物理地址连续的存储单元依次存储数据元素的线性结构,⼀般情况下采用数组存储。

         这里我们可以得知顺序表的逻辑结构(人为想象的结构)呈线性,同时它的物理结构是由连续的数组构成,所以它的物理结构也为线性。

2.2静态顺序表

概念:使用已经确定长度的数组存储元素,这里我们用代码来表示静态顺序表的结构:

#define N 7
typedef int SLDataType;
typedef struct SeqList
{SLDataType arr[N];int size;//有效的数据个数
};

         数组的长度我们无法改变,也就意味着我们无法随意的增加和删除数据,更不能在数据量变大时对储存数据的顺序表进行扩容,所以我们主要使用的顺序表为动态顺序表。

2.3动态顺序表

概念:使用可变长度的数组存储元素,这里我们使用代码来表示动态顺序表的基本结构:

typedef int SLDataType;typedef struct SepList
{SLDataType* arr;int capacity;int size;
}SL,*PSL;

三,动态顺序表的功能实现

         顺序表的目的是为了存储数据,所以我们这里所说的实现主要有头,尾插法。头,尾删法。定位插,删法。不过在此之前,如果空间的大小不够,我们将无法对数据进行增加,所以在进行所有的实现之前,我们需要先对空间大小进行检查:

3.1检查内存空间大小是否足够

         我们在扩充内存空间时,经常以原空间大小的倍数来扩充,这是因为随着我们扩充的次数增多,我们所需要存储的数据量也会按倍数增大,所以当我们以倍数来扩充内存空间时,正好与数据的增长量成线性关系,浪费的空间也将最大化的被缩小。通常情况下,储存空间我们以上次纯村空间的大小的二倍来增加,当然在此之前我们要对顺序表进行初始化:

void SepInit(PSL ps)
{ps->arr = NULL;ps->capacity = ps->size = 0;
}

对空间的大小检查的代码如下: 

void CheckSpace(PSL ps)
{if (ps->capacity == ps->size){int excapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;SLDataType* tmp = (SLDataType*)realloc(ps->arr, excapacity * sizeof(SLDataType));if (tmp == NULL){perror("SLInsertEnd,tmp:");return 1;}ps->arr = tmp;ps->capacity = excapacity;}
}

         这里我们需要对源顺序表进行检验,若它刚经过初始化,我们为它付一个初始值为4的容量(为什么不在初始化中对其进行赋值,我个人认为是因为后续对数据的增删可能会使顺序表变为空,在这里对其容量进行改动是为了避免这种情况),剩下就是正常的开辟顺序表的空间(使用realloc,因为realloc在对空指针增加空间后会返回一个新的地址对应开辟的空间,后续我们也需要对内存进行扩充,所以使用realloc最合适)。

3.2尾删法

顾名思义就是从尾部减少有效数据的个数,实现代码非常简单:

void SLDeltEnd(PSL ps)
{assert(ps);ps->size--;
}

3.3头删法

         这里我们需要从头部删除数据,其实就是把除了第一个数据外的所有数据整体向前移动一格,进而覆盖第一个数据,达到头删的目的,实现代码如下:

void SLDeltBeg(PSL ps)
{assert(ps);assert(ps->size);for (int i = 0; i < ps->size - 1; i++){ps->arr[i] = ps->arr[i + 1];}ps->size--;
}

当然我们需要判断有效数据的个数,如果为0就没有删除的必要了。 

3.4尾插法

         从尾部插入,其实就是向数组中的第size个位置插入数据,但如果数据在此之前已满,我们则需要扩充空间,具体实现代码如下:

void SLInsertEnd(PSL ps,SLDataType x)
{assert(ps);CheckSpace(ps);ps->arr[ps->size++] = x;
}

3.5头插法

         有了上面头删法的帮助,其实我们这里也就不难理解头删法是如何实现的,其实就是将现有数据整体向后移动一个位置,然后在首元素位置插入我们的数据,实现代码如下:

void SLInsertBeg(PSL ps,SLDataType x)
{assert(ps);CheckSpace(ps);for (int i = ps->size; i > 0; i--){ps->arr[i] = ps->arr[i - 1];}ps->arr[0] = x;ps->size++;
}

3.6定位删除法

         在这里我们需要注意,定位的方式删除与增加其实基本上沿用了头删与头插的思想,无非就是在传参时我们需要多传一个参数--需要删除或增加的位置,删除则将除了当前位置之后的所有元素整体向前移动一个位置,而增加则是将当前指定位置数据及之后的数据整体向后移动一个位置,然后再在当前位置放上我们的目标数据:

void SLDeltDes(PSL 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--;
}

3.7定位插入法

有了上面3.6的介绍,我们这里也不废话,直接上实现代码:

void SLDeltDes(PSL 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--;
}

         当然删除肯定要有数据才能删,有那个位置的空间才能定位增加数据,这也是我们上面使用assert断言的原因。 

四,实现功能后的善后处理

4.1打印顺序表内容

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

4.2释放顺序表

void SLDestory(PSL ps)
{if (ps->arr){free(ps->arr);}ps->capacity = 0;ps->size = 0;ps->arr = NULL;
}

4.3动态顺序表功能实现的完整代码

//头文件SepList.h
#pragma once
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>typedef int SLDataType;typedef struct SepList
{SLDataType* arr;int capacity;int size;
}SL,*PSL;void SepInit(PSL ps);//顺序表空间的初始化void SLInsertEnd(PSL ps,SLDataType x);//尾插法void SLPrintf(PSL ps);//检验打印void SLDestory(PSL ps);//释放开辟的动态内存void CheckSpace(PSL ps);//检查空间是否足够void SLInsertBeg(PSL ps,SLDataType x);//头插法void SLDeltBeg(PSL ps);//头删法void SLDeltEnd(PSL ps);//尾删法void SLDeltDes(PSL ps, int pos);//指定位置删除void SLInsertDes(PSL ps, int pos, SLDataType x);//指定位置增加数据//顺序表功能实现代码SepList.c
#include "Seplist.h"void SepInit(PSL ps)
{ps->arr = NULL;ps->capacity = ps->size = 0;
}void CheckSpace(PSL ps)
{if (ps->capacity == ps->size){int excapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;SLDataType* tmp = (SLDataType*)realloc(ps->arr, excapacity * sizeof(SLDataType));if (tmp == NULL){perror("SLInsertEnd,tmp:");return 1;}ps->arr = tmp;ps->capacity = excapacity;}
}void SLInsertEnd(PSL ps,SLDataType x)
{assert(ps);CheckSpace(ps);ps->arr[ps->size++] = x;
}void SLInsertBeg(PSL ps,SLDataType x)
{assert(ps);CheckSpace(ps);for (int i = ps->size; i > 0; i--){ps->arr[i] = ps->arr[i - 1];}ps->arr[0] = x;ps->size++;
}void SLPrintf(PSL ps)
{for (int i = 0; i < ps->size; i++){printf("%d ",ps->arr[i]);}printf("\n");
}void SLDestory(PSL ps)
{if (ps->arr){free(ps->arr);}ps->capacity = 0;ps->size = 0;ps->arr = NULL;
}void SLDeltBeg(PSL 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 SLDeltEnd(PSL ps)
{assert(ps);ps->size--;
}void SLDeltDes(PSL 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--;
}void SLInsertDes(PSL ps, int pos, SLDataType x)
{assert(ps);assert(pos >= 0 && pos <= ps->size);CheckSpace(ps);for (int i = ps->size; i > pos; i--){ps->arr[i] = ps->arr[i - 1];}ps->arr[pos] = x;ps->size++;
}//顺序表功能测试代码#include "Seplist.h"//顺序表的头插尾插以及头删尾删void test()
{SL s;SepInit(&s);SLInsertEnd(&s,4);SLInsertEnd(&s,5);SLInsertEnd(&s,3);SLInsertEnd(&s,2);SLInsertEnd(&s,1);SLInsertBeg(&s, 1);SLInsertBeg(&s, 2);SLInsertBeg(&s, 3);SLInsertBeg(&s, 4);SLDeltBeg(&s);SLDeltEnd(&s);SLDeltDes(&s, 2);SLInsertDes(&s, 4, 2);SLPrintf(&s);SLDestory(&s);
}int main()
{test();return 0;
}

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

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

相关文章

2. 白盒测试

白盒测试 1. 白盒测试定义 测试软件的内部编码和基础设施&#xff0c;重点是根据预期和期望的输出检查预定义的输入。它基于应用程序的内部工作方式&#xff0c;并围绕内部结构测试。在这种类型的测试中&#xff0c;编程测试用例需要编程技巧。白盒测试的主要目标是通过软件关…

秒懂设计模式--学习笔记(9)【结构型-装饰器模式】

目录 8、装饰器模式8.1 装饰器模式&#xff08;Decorator&#xff09;8.2 装修&#xff08;举例&#xff09;8.3 化妆&#xff08;示例&#xff09;8.4 化妆品的多样化8.5 装饰器8.6 自由嵌套8.7 装饰器模式的各角色定义8.8 装饰器模式 8、装饰器模式 8.1 装饰器模式&#xff…

MySQL运维实战之ProxySQL(9.6)SQL黑名单

作者&#xff1a;俊达 利用mysql_query_rules表中的error_msg字段&#xff0c;可以实现SQL黑名单的功能。如果规则设置了error_msg&#xff0c;当SQL语句匹配这条规则时&#xff0c;proxysql会直接将error_msg的内容返回给客户端。 当遇到一些大查询严重影响数据库性能时&…

【开源项目】Rust开发复制文件夹目录结构工具

说明 由于我经常需要在多个大容量的移动硬盘中查找和新增文件&#xff0c;我希望把硬盘的目录结构放到服务器的自建网盘中&#xff0c;因此开发了这个工具&#xff0c;使得在不同硬盘之间的文件管理变得更加便捷 项目地址&#xff1a;https://github.com/VinciYan/folder_clon…

红色文化3D虚拟数字展馆搭建意义深远

在房地产与土地市场的浪潮中&#xff0c;无论是新城规划、乡村振兴&#xff0c;还是商圈建设&#xff0c;借助VR全景制作、虚拟现实和web3d开发技术打造的全链条无缝VR看房新体验。不仅极大提升了带看与成交的转化率&#xff0c;更让购房者足不出户&#xff0c;即可享受身临其境…

Linux Cgroups

Linux CGroup全称Linux Control Group&#xff0c; 是Linux内核的一个功能&#xff0c;用来限制&#xff0c;控制与分离一个进程组群的资源&#xff08;如CPU、内存、磁盘输入输出等&#xff09;。这个项目最早是由Google的工程师在2006年发起&#xff08;主要是Paul Menage和R…

能把进程和线程讲的这么透彻的,没有20年功夫还真不行【0基础也能看懂】

本篇会加入个人的所谓鱼式疯言 ❤️❤️❤️鱼式疯言:❤️❤️❤️此疯言非彼疯言 而是理解过并总结出来通俗易懂的大白话, 小编会尽可能的在每个概念后插入鱼式疯言,帮助大家理解的. &#x1f92d;&#x1f92d;&#x1f92d;可能说的不是那么严谨.但小编初心是能让更多人…

【verilog】Verilog 中的 ifdef 语法指南:Verilog-2001 与 SystemVerilog

目录 简介 Verilog-2001 中的 ifdef 基本语法 示例 1&#xff1a;Verilog-2001 风格 SystemVerilog 中的 ifdef 基本语法 示例 2&#xff1a;SystemVerilog 风格 示例 3&#xff1a;调试与发布配置 注意事项 简介 在 Verilog 硬件描述语言中&#xff0c;ifdef 是一种…

SQL Server 创建用户并授权

创建用户前需要有一个数据库&#xff0c;创建数据库命令如下&#xff1a; CREATE DATABASE [数据库名称]; CREATE DATABASE database1; 一、创建登录用户 方式1&#xff1a;SQL命令 命令格式&#xff1a;CREATE LOGIN [用户名] WITH PASSWORD 密码; 例如&#xff0c;创建…

Vue项目中禁用ESLint的几种常见方法

1. 通过 vue.config.js 禁用 这是最直接且推荐的方式&#xff0c;因为它直接在Vue CLI的配置中禁用ESLint。通过在项目根目录下创建或修改 vue.config.js 文件&#xff0c;并设置 lintOnSave 为 false&#xff0c;可以彻底禁用保存时的ESLint检查。 // vue.config.js module…

FlinkErr:org/apache/hadoop/hive/ql/parse/SemanticException

在flink项目中跑 上面这段代码出现如下这个异常&#xff0c; java.lang.NoClassDefFoundError: org/apache/thrift/TException 加上下面这个依赖后不报错 <dependency> <groupId>org.apache.thrift</groupId> <artifactId>libthrift</artifactId…

Python绘制相关系数热力图

相关系数热力图是一种可视化工具&#xff0c;用于展示变量之间的相关性。它在数据分析和统计中非常有用&#xff0c;尤其是在探索数据集的内在关系时。本文将介绍如何使用Python绘制相关系数热力图。 一、准备——导入库 使用Pandas来处理数据&#xff0c;Matplotlib和Seabor…

力扣第233题“数字1的个数”

在本篇文章中&#xff0c;我们将详细解读力扣第233题“数字1的个数”。通过学习本篇文章&#xff0c;读者将掌握如何计算从1到n的数字中出现的“1”的个数&#xff0c;并了解相关的复杂度分析和模拟面试问答。每种方法都将配以详细的解释&#xff0c;以便于理解。 问题描述 力…

redis笔记2

redis是用c语言写的,放不频繁更新的数据&#xff08;用户数据。课程数据&#xff09; Redis 中&#xff0c;"穿透"通常指的是缓存穿透&#xff08;Cache Penetration&#xff09;问题&#xff0c;这是指一种恶意或非法请求直接绕过缓存层&#xff0c;直接访问数据库或…

力扣 144题 二叉树的前序遍历 记录

题目描述 给你二叉树的根节点 root &#xff0c;返回它节点值的 前序 遍历。输入&#xff1a;root [1,null,2,3] 输出&#xff1a;[1,2,3]思路 辅助函数 traversal:- 参数: 接受两个参数&#xff0c;一个是指向树节点的指针 cur&#xff08;表示当前访问的节点&#xff09;&…

Qt | 绘制椭圆、弧、弦、扇形、圆角矩形

点击上方"蓝字"关注我们 01、简介 1、需要使用到的 QPainter 类中的函数 2、绘制椭圆的方法有 绘制给定矩形的内接椭圆和根据中心点与椭圆 x 方向和 y 方向的半径绘制,原理见下图 3、绘制弧、弦、扇形的原理: 1)、弧是椭圆上的一段曲线,因此其绘制方法就是首先…

STM32之八:IIC通信协议

目录 1. IIC协议简介 1.1 主从模式 1.2 2根通信线 2. IIC协议时序 2.1 起始条件和终止条件 2.2 发送一个字节 2.3 接收一个字节 2.4 应答信号 1. IIC协议简介 IIC协议是一个半双工、同步、一主多从、多主多从的串行通用数据总线。该通信模式需要2根线&#xff1a;SCL、…

ubuntu22.04安装SecureCRT8.7.3,完成顺利使用

材料准备 scrt-sfx安装包 &#xff0c; securecrt_linux_crack.pl 补丁脚本&#xff0c;和两个依赖库 其中securecrt_linux_crack.pl是找的专门适合 8.7.3版本的&#xff0c;网上很多版本的crack.pl只能打补丁以前的老版本。 而更老版本的SecureCRT对ubuntu22支持更不好&#…

【低照度图像增强系列(8)】URetinex-Net算法详解与代码实现(2022|CVPR)

前言 ☀️ 在低照度场景下进行目标检测任务&#xff0c;常存在图像RGB特征信息少、提取特征困难、目标识别和定位精度低等问题&#xff0c;给检测带来一定的难度。 &#x1f33b;使用图像增强模块对原始图像进行画质提升&#xff0c;恢复各类图像信息&#xff0c;再使用目标检…

hmallox勒索病毒科普:了解其威胁与防御策略

hmallox勒索病毒科普&#xff1a;了解其威胁与防御策略 一、引言 在数字化时代&#xff0c;网络安全威胁日益严峻&#xff0c;勒索病毒作为其中的一类恶意软件&#xff0c;给个人和企业带来了巨大损失。hmallox勒索病毒作为Mallox勒索软件家族的新变种&#xff0c;以其高度的…