数据结构·一篇搞定顺序表!

大家好啊,几日不见,甚是想念,从这一篇文章开始,我们就要进入数据结构了哦,那么我们废话不多说,今天我们一起来搞定顺序表!!!
请添加图片描述

1. 顺序表概念及结构

顺序表是一种线性结构,它由一组连续的存储单元(通常是数组)组成,数据元素之间的关系是相邻的。顺序表中的元素是按照一定的顺序排列的,可以通过下标来访问和操作各个元素。顺序表的结构简单、易于实现,是一种常见的数据结构之一。

2. 顺序表分类

• 顺序表和数组的区别
◦ 顺序表的底层结构是数组,对数组的封装,实现了常⽤的增删改查等接口

静态顺序表

#define MAX_SIZE 10typedef struct {int data[MAX_SIZE];int length;
} StaticList;

在这个例子中,我们定义了一个包含10个整数元素的静态顺序表,其中data数组存储元素,length表示当前顺序表中元素的个数。在使用静态顺序表时,需要注意不要超出预先定义的最大长度,否则可能导致数组越界错误.

动态顺序表

在这里插入图片描述
我们一般使用顺序表都是动态顺序表,这样的话才可以进行增删改查的操作,那么我们接下来就来康康这些操作~

3. 实现动态顺序表

#define INIT_CAPACITY 4
typedef int SLDataType;
// 动态顺序表 -- 按需申请
typedef struct SeqList
{SLDataType* a;int size; // 有效数据个数int capacity; // 空间容量
}SL;
//初始化和销毁
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);
//指定位置之前插⼊/删除数据
void SLInsert(SL* ps, int pos, SLDataType x);
void SLErase(SL* ps, int pos);
int SLFind(SL* ps, SLDataType x);

下面是实现的代码

#define INIT_CAPACITY 4  typedef int SLDataType;  typedef struct SeqList {  SLDataType* a;  int size; // 有效数据个数  int capacity; // 空间容量  
} SL;  

3.1 初始化

// 初始化  
void SLInit(SL* ps) {  ps->a = (SLDataType*)malloc(INIT_CAPACITY * sizeof(SLDataType));  if (!ps->a) {  exit(EXIT_FAILURE); // 分配内存失败  }  ps->size = 0;  ps->capacity = INIT_CAPACITY;  
}  
  1. 通过 malloc 函数为顺序线性表的数组成员 a 分配内存空间,大小为 INIT_CAPACITY *
    sizeof(SLDataType),其中 INIT_CAPACITY 是一个预先定义的常量,表示初始容量。
  2. 检查内存分配是否成功,如果分配失败(即 ps->a 为 NULL),则调用 exit(EXIT_FAILURE)
    函数退出程序。
  3. 将顺序线性表的 size 成员初始化为 0,表示当前表中没有元素。
  4. 将顺序线性表的 capacity 成员初始化为INIT_CAPACITY,表示表的初始容量为 INIT_CAPACITY。

3.2 销毁

void SLDestroy(SL* ps) {  free(ps->a);  ps->a = NULL;  ps->size = 0;  ps->capacity = 0;  
}  
  1. 调用 free 函数释放顺序线性表的数组成员 a 所占用的内存空间,这样可以避免内存泄漏。
  2. 将顺序线性表的 a 成员指针设置为 NULL,这是一种良好的习惯,可以避免出现野指针访问的问题。
  3. 将顺序线性表的 size 成员设为 0,表示表中不再有元素。
  4. 将顺序线性表的 capacity 成员设为 0,表示表的容量为 0。

3.3 打印

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

这个没什么好说的吧哈哈哈

3.4 扩容

void SLCheckCapacity(SL* ps) {  if (ps->size == ps->capacity) {  ps->capacity *= 2;  SLDataType* temp = (SLDataType*)realloc(ps->a, ps->capacity * sizeof(SLDataType));  if (!temp) {  exit(EXIT_FAILURE); // 扩容失败  }  ps->a = temp;  }  
}  
  1. 判断顺序线性表的当前大小(size)是否等于容量(capacity),如果相等,则表示表中元素已经填满,需要进行扩容操作。
  2. 将顺序线性表的容量 capacity 扩大为原来的两倍,即 ps->capacity *= 2;,这里采用了简单的扩容策略。
  3. 调用 realloc 函数重新分配内存空间,将原来的数据拷贝到新的空间中,大小为 ps->capacity *
    sizeof(SLDataType)。
  4. 检查是否成功分配新的内存空间,如果分配失败(即 temp 为 NULL),则调用 exit(EXIT_FAILURE)
    函数退出程序。
  5. 将新分配的内存空间的地址赋值给顺序线性表的数组成员 a,完成扩容操作。

3.5 头部插入

void SLPushFront(SL* ps, SLDataType x) {  SLCheckCapacity(ps);  for (int i = ps->size; i > 0; i--) {  ps->a[i] = ps->a[i - 1];  }  ps->a[0] = x;  ps->size++;  
}  
  1. 调用 SLCheckCapacity 函数,确保顺序线性表有足够的容量来存储新的元素。
  2. 从顺序线性表的最后一个元素开始,依次将元素向后移动一个位置,为新元素腾出空间。这里使用循环从 ps->size
    开始,依次向前移动元素,直到第一个元素。
  3. 将要插入的新元素 x 放入顺序线性表的第一个位置,即头部位置。
  4. 增加顺序线性表的大小 size,表示表中元素数量增加了一个。

3.6 头部删除

void SLPopFront(SL* ps) {  if (ps->size == 0) {  return;  }  for (int i = 0; i < ps->size - 1; i++) {  ps->a[i] = ps->a[i + 1];  }  ps->size--;  
}  
  1. 判断顺序线性表的大小(size)是否为0,如果是空表(size == 0),则直接返回,不进行删除操作。
  2. 从顺序线性表的第一个元素开始,依次将元素向前移动一个位置,覆盖掉原来的元素。这里使用循环从0开始,依次向后移动元素,直到倒数第二个元素。
  3. 减少顺序线性表的大小 size,表示表中元素数量减少了一个。

3.7 尾部插入

void SLPushBack(SL* ps, SLDataType x) {  SLCheckCapacity(ps);  ps->a[ps->size] = x;  ps->size++;  
}  
  1. 调用 SLCheckCapacity 函数,确保顺序线性表有足够的容量来存储新的元素。
  2. 将要插入的新元素 x 放入顺序线性表当前大小(size)的位置,即在尾部插入。
  3. 增加顺序线性表的大小 size,表示表中元素数量增加了一个。

3.8 尾部删除

不用说吧~~~

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

3.9 指定位置之前插入数据

void SLInsert(SL* ps, int pos, SLDataType x) {  if (pos < 0 || pos > ps->size) {  return; // 插入位置不合理  }  SLCheckCapacity(ps);  for (int i = ps->size; i > pos; i--) {  ps->a[i] = ps->a[i - 1];  }  ps->a[pos] = x;  ps->size++;  
}  
  1. 判断插入位置 pos 是否合理,即必须满足 pos >= 0 且 pos <= ps->size,否则直接返回,不进行插入操作。
  2. 调用 SLCheckCapacity 函数,确保顺序线性表有足够的容量来存储新的元素。
  3. 从顺序线性表的最后一个元素开始,依次将元素向后移动一个位置,为新元素腾出空间。这里使用循环从 ps->size开始,依次向前移动元素,直到插入位置 pos。
  4. 将要插入的新元素 x 放入顺序线性表的指定位置 pos。
  5. 增加顺序线性表的大小 size,表示表中元素数量增加了一个.

3.10 指定位置删除数据

void SLErase(SL* ps, int pos) {  if (pos < 0 || pos >= ps->size) {  return; // 删除位置不合理  }  for (int i = pos; i < ps->size - 1; i++) {  ps->a[i] = ps->a[i + 1];  }  ps->size--;  
}  
  1. 判断删除位置 pos 是否合理,即必须满足 pos >= 0 且 pos < ps->size,否则直接返回,不进行删除操作。
  2. 从指定位置 pos 开始,将后面的元素依次向前移动一个位置,覆盖掉要删除的元素。这里使用循环从 pos
    开始,依次将元素向前移动,直到倒数第二个元素。
  3. 减少顺序线性表的大小 size,表示表中元素数量减少了一个,相当于删除了一个元素。

3.11 查找数据

int SLFind(SL* ps, SLDataType x) {  for (int i = 0; i < ps->size; i++) {  if (ps->a[i] == x) {  return i; // 返回数据下标  }  }  return -1; // 没有找到数据  
}  

4. 基于动态顺序表实现通讯录项目

相信大家掌握了上面的操作后,实现通讯录并不是啥难事,肖恩在这也不细细讲解了,希望大家理解哦~~~请添加图片描述

由于这个通讯录的代码有一点点多,放在这里大家也不好学习,我直接放个链接吧,大家直接点开就欧克了,也方便copy.
通讯录

5. 顺序表经典算法

这是两个有关顺序表的经典的算法的,大家点开链接可以做做,同样,我把代码放在这,大家自行悟道
经典算法OJ题1: 移除元素

int removeElement(int* nums, int numsSize, int val) {int i, j;for(i = 0, j = 0; i < numsSize; i++){if(nums[i] != val){nums[j] = nums[i];j++;}}return j;
}

经典算法OJ题2: 合并两个有序数组

void merge(int* nums1, int nums1Size, int m, int* nums2, int nums2Size, int n) {
int p1 = m - 1;int p2 = n - 1;int p = m + n - 1;while(p1 >= 0 && p2 >= 0){if(nums1[p1] > nums2[p2]){nums1[p] = nums1[p1];p1--;} else {nums1[p] = nums2[p2];p2--;}p--;}while(p2 >= 0){nums1[p] = nums2[p2];p2--;p--;}
}

大家要是有比这个好的方法那就更好了!还是比肖恩强的哈哈哈

6. 顺序表的问题及思考*

  1. 中间/头部的插入删除,时间复杂度为O(N)
  2. 增容需要申请新空间,拷贝数据,释放旧空间。会有不小的消耗。
  3. 增容一般是呈2倍的增长,势必会有一定的空间浪费。例如当前容量为100,满了以后增容到200,我们再继续插入了5个数据,后面没有数据插入了,那么就浪费了95个数据空间。

思考:如何解决以上问题呢?

在这里插入图片描述
下期预告
那当然是…Linked List

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

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

相关文章

VBA脚本终章编译器崩溃

一、介绍 本篇文章为VBA脚本隐藏技术的最后一篇&#xff0c;将介绍如何在保证VBA脚本正常执行的情况下&#xff0c;使分析人员无法打开编译器。 那么为什么需要分析人员无法打开编译器呢&#xff1f; 首先&#xff0c;我们需要引入一个知识点。 在上篇《VBA隐藏技术stompin…

系统思考—战略

“有策略而无战术&#xff0c;是取胜之最慢之道。有战术而无策略&#xff0c;是败亡之前的嘈杂。”—孙子 最近接触的中小企业&#xff0c;充分能感受到在经济下行的情况下&#xff0c;组织与战略是不可分割的两个方面。有时候公司组织出现了问题&#xff0c;可能是因为战略不…

maven3.9的settings.xml 内容学习

settings.xml 文件介绍 settings.xml 是 Maven 的配置文件&#xff0c;它允许你自定义 Maven 的行为&#xff0c;比如设置仓库、代理、认证信息等。在 Maven 3.9 中&#xff0c;settings.xml 的结构和内容可能与之前的版本相似&#xff0c;但可能会有一些小的改进或变化。下面…

单分支:if语句

示例&#xff1a; /*** brief how about if? show you here.* author wenxuanpei* email 15873152445163.com(query for any question here)*/ #define _CRT_SECURE_NO_WARNINGS//support c-library in Microsoft-Visual-Studio #include <stdio.h>#define if_state…

MoJoCo 入门教程(七)XML 参考

系列文章目录 前言 表格第二列中的符号含义如下&#xff1a; ! 必填元素&#xff0c;只能出现一次 ? 可选元素&#xff0c;只能出现一次 * 可选元素&#xff0c;可多次出现 R 可选元素&#xff0c;可递归出现多次 一、简介 本章是 MuJoCo 中使用的 MJCF 建模语言的参考手册。…

【投稿优惠|稳定检索】2024年低碳发展与地球科学国际会议 (LCDES 2024)

2024年低碳发展与地球科学国际会议 (LCDES 2024) 2024 International Conference on Low Carbon Development and Earth Science 【会议简介】 2024年低碳发展与地球科学国际会议即将在长沙盛大召开。本次会议将汇聚全球低碳发展与地球科学领域的专家学者&#xff0c;共同探讨…

登录解析(前端)

登录代码 1、登录之后做了什么&#xff1f; 执行登陆方法&#xff0c;成功之后&#xff0c;路由跳转到指定路径或者根目录 2、this.$store.dispatch是什么意思&#xff1f; this.$store.dispatch(‘Login’, this.loginForm) 来调取store里的user.js的login方法3、this.$r…

将MySQL数据库导入到EA模型的教程

将MySQL数据库导入到EA 1.下载安装mysql-connector-odbc2.在管理工具中新增ODBC数据源3.在EA中新建项目4.链接MYSQL数据源4.1 安装64位的ODBC驱动可能出现”在连接ODBC 时发生错误&#xff0c;请相关检查设置“的提示&#xff0c;卸载后重新安装32位ODBC驱动后可以正常执行 5.导…

智慧园区引领产业智能化升级:科技创新驱动打造智慧化、高效化产业新未来

随着全球科技革命的深入推进&#xff0c;以大数据、云计算、物联网、人工智能等为代表的新一代信息技术正深刻改变着传统产业的发展模式。在这一背景下&#xff0c;智慧园区作为产业智能化升级的重要载体和平台&#xff0c;正以其前瞻性的规划、创新的科技和卓越的实践&#xf…

OpenCV杂记(2):图像拼接(hconcat, vconcat)

OpenCV杂记&#xff08;1&#xff09;&#xff1a;绘制OSD&#xff08;cv::getTextSize, cv::putText&#xff09;https://blog.csdn.net/tecsai/article/details/137872058 1. 简述 做图像处理或计算机视觉技术的同学都知道&#xff0c;我们在工作中会经常遇到需要将两幅图像拼…

IntelliJ-platform plugIn 插件开发专题内容介绍,学习指导(一)

这系列文章出炉对于笔者来说确实不容易&#xff0c;历时快两年了&#xff0c;先后迭代了3版本&#xff0c;暂时与官方最新版本API同步&#xff08;2024.03&#xff09;&#xff0c;文章内容覆盖2022~2024版内容 专题由来 最早接触插件开发是源于公司一个国际化项目&#xff0c…

以pytorch pipeline并行为例,分析各kernel的耗时占比及性能瓶颈

以pytorch pipeline并行为例,分析各kernel的耗时占比及性能瓶颈 1.生成pipeline并行的测试代码2.pipeline profing3.生成nsys2json.py代码4.将nsys sqlite格式转chrome json格式5.生成耗时成分统计代码6.统计耗时成分7.耗时成分如下:8.查看GPU PCIE链路状态9.链路状态如下10.Ns…

Unity地形关联出错的解决办法以及地形深度拷贝

问题 最近发现unity地形系统的一个bug&#xff0c;导入的场景地形数据关联错乱了&#xff0c;关联到别的场景的地形数据了&#xff0c;meta替换了也没用&#xff0c;不清楚它具体是怎么关联的。 看下面的案例&#xff1a; 可以看到正常这个场景的地形数据应该关联的是Scene_E…

gma 2 用户文档(pdf版)更新计划

随着 gma 2 整体构建完成&#xff0c;下一步继续针对库内所有功能完成一个用户指南&#xff08;非网站&#xff09;。相较于上次更新用户文档pdf版&#xff0c;已经过去了大半年。当然&#xff0c;PDF 版比网站上内容更丰富&#xff0c;也更新&#xff08;文档基于 gma 2.0.9a2…

【Java】集合概念及多线程

HashSet 、 LinkedHashSet 和 TreeSet 的主要区别在于底层数据结构不同。 HashSet 的底层数据结构是哈希表&#xff08;基于 HashMap 实现&#xff09;。 LinkedHashSet 的底层数据结构是链表和哈希表&#xff0c;元素的插⼊和取出顺序满⾜ FIFO。 TreeSet 底层数据结构是红…

Linux系统下使用Parted调整物理分区大小

前言 在管理Linux系统时&#xff0c;有时需要对物理分区大小进行调整以满足不断变化的需求。Parted是一款功能强大的分区管理工具&#xff0c;可以帮助您轻松地进行这项任务。本文将简要介绍如何使用Parted来调整物理分区大小&#xff0c;让您能够快速且安全地完成这一操作。 …

【前端】4. CSS综合案例

1. 模拟新闻界面 <!-- 1.模拟实现新闻界面 --><!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>…

YMP实现Oracle迁移到YashanDB

迁移需求 ip地址 数据库信息 操作系统信息 源库 192.168.3.132 实例名topdh 用户密码TOPICIS/oracle 端口1521 Centos7.9 x86_64 目标库 192.168.3.175 实例名yasdb 用户密码topicist/opicis 端口1688 Centos7.9 x86_64 迁移前准备 YMP工具获取 根据实际需求向厂…

sklearn【AUC-ROC】原理,以及绘制ROC曲线!

一、AUC-ROC 介绍 在分类任务中&#xff0c;特别是当数据集中的类别分布不平衡时&#xff0c;评估模型的性能变得尤为重要。AUC-ROC&#xff08;Area Under the Receiver Operating Characteristic Curve&#xff0c;受试者工作特征曲线下的面积&#xff09;是一种有效的评估指…

Vue3:组合式API的基本使用

一、前言 本文主要讲述在Vue3中组合式API的基本使用。 二、组合式API的写法 1、数据 组合式API中&#xff0c;数据在setup函数里面声明数据要在return中返回才能在模板中渲染使用如果数据类型不是响应式数据&#xff0c;当数据改变时&#xff0c;已经展示在页面上的数据不会…