【数据结构】——顺序表详解

大家好!当我们学习了动态内存管理后,就可以写一个管理数据的顺序表了!!!

顺序表的理解:

线性表是最基本、最简单、也是最常用的一种数据结构。线性表(linear list)是数据结构的一种,一个线性表是n个具有相同特性的数据元素的有限序列。

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

在这里插入图片描述

静态顺序表就是像数组一样的大小固定的,动态的可以在容量不够时进行扩容而达到能够存储大量数据的效果!!!

一、先创建一个结构体来表示顺序表

typedef int DATE;//重命名顺序表的数据类型
typedef struct ArrayList {DATE* date;size_t size;//顺序表长度size_t capacity;//顺序表容量
}AL;

二、顺序表的所有接口展示

void Init(AL* al);
void checkCapacity(AL* al);
void pushBack(AL* al, DATE info);
void pushFront(AL* al, DATE info);
void insertDate(AL* al,size_t pos, DATE info);
void printDate(AL* al);
void Erase(AL* al, size_t pos);
void PopBack(AL* al);
void PopFront(AL* al);
size_t FindDate(AL* al, DATE info);
void ExchangeDate(AL* al, size_t pos, DATE info);
void Deatory(AL* al);

三、每个接口功能介绍及实现原理

1、初始化函数的实现

void Init(AL* al)
{assert(al);al->size = 0;al->capacity = 4;//初始化容量为4DATE* tmp = (DATE*)malloc(sizeof(DATE) * al->capacity);if (tmp == NULL){perror("malloc fail");exit(-1);}al->date = tmp;
}

初始化顺序表的长度为0、容量为4!

2、检查容量函数的实现

void checkCapacity(AL* al)
{if (al->size == al->capacity){DATE* tmp = (DATE*)realloc(al->date, sizeof(DATE) * al->capacity*2);if (tmp == NULL){perror("realloc fail");exit(-1);}al->capacity *= 2;al->date = tmp;printf("扩容成功!\n");}
}

如果长度等于容量时就说明需要扩容了,就将容量扩到2倍大小

3、尾插函数的实现

void pushBack(AL* al, DATE info)
{assert(al);checkCapacity(al);al->date[al->size] = info;al->size++;
}

每次插入之前一定要检查容量
尾插就是在size尾位置写入需要插入的值,然后要对长度进行加一
在这里插入图片描述

4、头插函数的实现

void pushFront(AL* al, DATE info)
{assert(al);checkCapacity(al);if (al->size == 0){al->date[0] = info;al->size++;}else{size_t end = al->size;while (end){al->date[end] = al->date[end-1];end--;}al->date[0] = info;al->size++;}
}

头插一个数据,必须将后面的数据向后面移动,移动的过程中可能超过容量大小,所以在插入时都需要进行扩容判断

在这里插入图片描述

挪动方法如上

在这里插入图片描述

5、尾删函数

void PopBack(AL* al)
{assert(ps);assert(al->size > 0);al->size--;
}

将长度减一即可删除最后一个数据

6、头删函数

void PopFront(AL* al)
{assert(al->size > 0);int begin = 1;while (begin<al->size){al->date[begin - 1] = al->date[begin];begin++;}al->size--;
}

挪动顺序方法如下:
在这里插入图片描述
定义一个变量begin=1,首先是要将数据2移动到数据1的位置,对应的操作是
al->date[begin - 1] = al->date[begin];然后begin++,依次将数据3挪到数据2的位置,数据4挪到数据3的位置。循环最后一次是将数据5挪到数据4的位置,也就是begin=4,al->size=5.则循环判断条件为beginsize,循环结束后将
al->size–;

在这里插入图片描述

7、任意位置删除数据函数的实现

void Erase(AL* al, size_t pos)
{assert(al);assert(pos >= 0 && pos <= al->size);if (al->size == 0){printf("暂无数据!!\n");return;}size_t end = pos;while (end<al->size-1){![在这里插入图片描述](https://img-blog.csdnimg.cn/a1a63c6776c142eeb77e15536b8f9a53.png#pic_center)al->date[end] = al->date[end + 1];end++;}al->size--;
}

删除一个数据,就要将这个位置之后的元素全部向前挪动一个位置
由于下标易班都有size_t表示,所以一个要把握好头删时出现无符号-1和0循环条件比较大小的情况

如果我们要删除数3,然后数据3后面的数据向前挪动,第一步就是将数据4移动到数据3的位置,定义一个变量end=pos=2;对应的操作为al->date[end] = al->date[end+1];,然后end++;将数据5移动到最开始数据4的地方。最后一次循环是将数据5移动到数据4的地方,也就是end最后等于3,al->size=5,则循环判断条件是end< al->size-1,循环结束将al->size–;

在这里插入图片描述

8、任意位置插入数据函数的实现

void insertDate(AL* al, size_t pos, DATE info)
{assert(al);assert(pos >= 0 && pos <= al->size);checkCapacity(al);int end = al->size;while (end > pos){al->date[end] = al->date[end - 1];end--;}al->date[pos] = info;al->size++;
}

由于下标易班都有size_t表示,所以一个要把握好头插时出现无符号-1和0循环条件比较大小的情况

在这里插入图片描述

任意位置插入需要将插入位置及其以后的数据一次向后挪动一个位置!

9、头插头删和头删尾删函数的改进

我们写完任意插和任意删后,就可以对头插头删和头删尾删函数的改进,直接在他们的函数体里面调用任意插入和任意删除函数

void pushFront(AL* al, DATE info)
{assert(al);checkCapacity(al);if (al->size == 0){al->date[0] = info;al->size++;}else{insertDate(al, 0, info);}
}
void pushBack(AL* al, DATE info)
{assert(al);checkCapacity(al);insertDate(al, al->size, info);
}
void PopBack(AL* al)
{assert(al);if (al->size == 0){printf("暂无数据!!\n");return;}Erase(al, al->size);}
void PopFront(AL* al)
{assert(al);if (al->size == 0){printf("暂无数据!!\n");return;}Erase(al, 0);
}

头插就是调用insert函数在0位置插入
尾插就是调用insert函数在size位置插入
头删就是调用Erase函数删除0位置
尾删就是调用Erase函数删除size位置

10、查找数据函数实现

size_t FindDate(AL* al, DATE info)
{assert(al);for (size_t i = 0; i < al->size; i++){if (al->date[i] == info)return i;}return -1;
}

依次便利顺序表,如果找到需要查找的数据,咋返回其下标,否则返回-1

11、修改数据

void ExchangeDate(AL* al, size_t pos, DATE info)
{assert(al);assert(pos >= 0 && pos <= al->size);al->date[pos] = info;
}

先查找要修改的数据是否存在,然后进行修改
他一般会和查找函数配合使用

在这里插入图片描述

12、销毁顺序表

由于顺序表开辟了堆区内存,所以我们在使用完顺序表后一定要对开辟的内存进行释放!

void Deatory(AL* al)
{assert(al);free(al->date);al->date=NULL;al->capacity = al->size = 0;
}

销毁一个顺序表,将顺序表的容量置为0,顺序表的有效数据个数置为0,将date指针所指向的动态开辟的内存空间释放了,由于释放了动态开辟的内存空间,所有p指向的空间未初始化,date成为野指针,为了防止野指针,将date置为空指针。

数据结构篇之——顺序表的分享到这里就结束了,感谢大家的浏览访问!!!

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

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

相关文章

青藏高原1-km分辨率生态环境质量变化数据集(2000-2020)

青藏高原平均海拔4000米以上&#xff0c;人口1300万&#xff0c;是亚洲九大河流的源头&#xff0c;为超过15亿人口提供淡水、食物和其他生态系统服务&#xff0c;被誉为地球第三极和亚洲水塔。然而&#xff0c;在该地区的人与自然的关系的研究是有限的&#xff0c;尤其是在精细…

高德地图根据两点的经纬度计算两点之间的距离(修正版)

SQL语句可以用来计算两个经纬度之间的距离。下面是一个示例的SQL语句&#xff1a; SELECT id, ( 6371 * ACOS( COS( RADIANS( lat1 ) ) * COS( RADIANS( lat2 ) ) * COS( RADIANS( lng2 ) - RADIANS( lng1 ) ) SIN( RADIANS( lat1 ) ) * SIN( RADIANS( lat2 ) ) ) ) AS dista…

PyTorch - 模型训练损失 (Loss) NaN 问题的解决方案

欢迎关注我的CSDN&#xff1a;https://spike.blog.csdn.net/ 本文地址&#xff1a;https://spike.blog.csdn.net/article/details/133378367 在模型训练中&#xff0c;如果出现 NaN 的问题&#xff0c;严重影响 Loss 的反传过程&#xff0c;因此&#xff0c;需要加入一些微小值…

【RabbitMQ实战】07 3分钟部署一个RabbitMQ集群

一、集群的安装部署 我们还是利用docker来安装RabbitMQ集群。3分钟安装一个集群&#xff0c;开始。 前提条件&#xff0c;docker安装了docker-compose。如果没安装的话&#xff0c;参考这里 docker-compose文件参考bitnami官网&#xff1a;https://github.com/bitnami/contai…

巧用@Conditional注解根据配置文件注入不同的bean对象

项目中使用了mq&#xff0c;kafka两种消息队列进行发送数据&#xff0c;为了避免硬编码&#xff0c;在项目中通过不同的配置文件自动识别具体消息队列策略。这里整理两种实施方案&#xff0c;仅供参考&#xff01; 方案一&#xff1a;创建一个工具类&#xff0c;然后根据配置文…

Swift 周报 第三十八期

文章目录 前言新闻和社区苹果自研调制解调器芯片受挫&#xff1a;速度太慢容易过热&#xff0c;落后高通 3 年App Store 现已接受适用于最新版操作系统的 App 和游戏提交 提案通过的提案正在审查的提案驳回的提案 Swift论坛推荐博文话题讨论关于我们 前言 本期是 Swift 编辑组…

vue 实现弹出菜单,解决鼠标点击其他区域的检测问题

弹出菜单应该具有的功能&#xff0c;当鼠标点击其他区域时&#xff0c;则关闭该菜单。 问题来了&#xff0c;怎么检测鼠标点击了其他区域而不是当前菜单&#xff1f; 百度“JS检测区域外的点击事件”&#xff0c;会发现有很多方法&#xff0c;有递归检测父元素&#xff0c;有遍…

Blender导出FBX给UE5

最近在学习UE5的资源导入&#xff0c;总结如下&#xff1a; 建模使用Blender&#xff0c;UE5版本是5.3 1.纯静态模型导入UE5 Blender FBX导出设置保持默认即可&#xff0c; UE5把导入设置里Miscellaneous下Force Front XAxis和Convert Scene Unit勾选即可 2.带骨骼动画的模型…

react项目优化

随着项目体积增大&#xff0c;打包的文件体积会越来越大&#xff0c;需要优化&#xff0c;原因无非就是引入的第三方插件比较大导致&#xff0c;下面我们先介绍如何分析各个文件占用体积的大小。 1.webpack-bundle-analyzer插件 如果是webpack作为打包工具的项目可以使用&…

MySQL 连接查询(多表查询 二)

基本介绍 作用&#xff1a;连接查询&#xff08;Join&#xff09;操作&#xff0c;用于联结多个表以获取更全面和准确的数据 基本分类&#xff1a; 内连接&#xff1a;相当于查询A、B交集部分数据&#xff08;去掉迪卡尔积无效组合&#xff09;外连接&#xff1a; 左外连接&…

lwIP 开发指南(下)

目录 NETCONN 编程接口简介netbuf 数据缓冲区netconn 连接结构netconn 编程API 函数 NETCONN 编程接口UDP 实验NETCONN 实现UDPNETCONN 接口的UDP 实验硬件设计软件设计下载验证 NETCONN 接口编程TCP 客户端实验NETCONN 实现TCP 客户端连接步骤NETCONN 接口的TCPClient 实验硬件…

freertos中函数调用和启动第一个任务(栈相关!!!!!!)

本内容仅就一些较难理解的点讲解&#xff0c;请结合其它文章实用 在函数调用时&#xff0c;m3的处理器使用r0-r3共四个寄存器传参&#xff0c;其余的使用栈传参。 但是&#xff0c;如果传入的参数是全局变量&#xff0c;则不需传参&#xff0c;因为全局变量在函数内部是可见的…

【算法练习Day8】 kmp算法找出字符串中第一个匹配项的下标反转字符串中的单词重复的子字符串

、​ ​&#x1f4dd;个人主页&#xff1a;Sherry的成长之路 &#x1f3e0;学习社区&#xff1a;Sherry的成长之路&#xff08;个人社区&#xff09; &#x1f4d6;专栏链接&#xff1a;练题 &#x1f3af;长路漫漫浩浩&#xff0c;万事皆有期待 文章目录 kmp算法找出字符串中第…

2023版 STM32实战5 基本定时器中断

基本定时器简介与特性 -1-时钟可分频 -2-计数模式只可以选择累加 -3-只可以用来定时&#xff08;含中断&#xff09; 查看时钟源 如图定时器7的时钟最大为72MHZ 定时时间的计算 通用定时器的时间计算公式为 Tout &#xff08;&#xff08;arr1&#xff09;&#xff08;psc1&…

Spring修炼之路(2)依赖注入(DI)

一、概念 依赖注入&#xff08;Dependency Injection,DI&#xff09;。 测试pojo类 : Address.java 依赖 : 指Bean对象的创建依赖于容器 . Bean对象的依赖资源 . 注入 : 指Bean对象所依赖的资源 , 由容器来设置和装配 . 二、 注入方式 2.1构造器注入 我们在之前的案例已经…

【Java】异常

1. Java的异常概念 1.1 异常体系结构 从上图中可以看到&#xff1a; 1. Throwable&#xff1a;是异常体系的顶层类&#xff0c;其派生出两个重要的子类, Error 和 Exception 2. Error&#xff1a;指的是JVM无法解决的严重问题&#xff0c;比如&#xff1a;JVM的内部错误、资源…

Apache Flume

Flume 1.9.0 Developer Guide【Flume 1.9.0开发人员指南】 Introduction【介绍】 摘自&#xff1a;Flume 1.9.0 Developer Guide — Apache Flume Overview【概述】 Apache Flume is a distributed, reliable, and available system for efficiently collecting, aggregati…

PHP8中的构造方法和析构方法-PHP8知识详解

今日分享的内容是php8中的构造方法和析构方法&#xff0c;我们把构造方法和析构方法这两个方法分开来讲&#xff1a; 1、构造方法 构造方法存在于每个声明的类中&#xff0c;主要作用是执行一些初始化任务。如果类中没有直接声明构造方法&#xff0c;那么类会默认地生成一个没…

江西广电会展集团总经理李悦一行莅临拓世科技集团调研参观,科技璀璨AIGC掀新潮

在江西这片充满活力的土地上&#xff0c;数字经济如潮水般涌动&#xff0c;会展文化与科技的完美结合&#xff0c;正如新时代的璀璨繁星照亮夜空&#xff0c;更预示着一场AIGC创新的壮丽篇章即将展开。作为拓世科技集团的老朋友&#xff0c;江西广电多位领导多次莅临拓世科技集…

2023-9-29 JZ27 二叉树的镜像

题目链接&#xff1a;二叉树的镜像 import java.util.*;/** public class TreeNode {* int val 0;* TreeNode left null;* TreeNode right null;* public TreeNode(int val) {* this.val val;* }* }*/public class Solution {/*** 代码中的类名、方法名、参数…