01数据结构 - 顺序表

这里是只讲干货不讲废话的炽念,这个系列的文章是为了我自己以后复习数据结构而写,所以可能会用一种我自己能够听懂的方式来描述,不会像书本上那么枯燥和无聊,且全系列的代码均是可运行的代码,关键地方会给出注释^_^

全文近8000字

版本:C++17

编译器:Clion 2023.3.24

暂时只给出代码,不会涉及到基础知识的讲解

1.线性表的定义

//定义顺序表的表头结构
typedef struct {Element* data;              // 指向顺序表的数据区域int len;                    // 该区域能够访问的边界条件,目前内容器存储数据的数量int cap;                    // 该区域最大容量,超过这个容量就需要扩容
}SeqList;// len 始终指向待插入位置

2.线性表的实现函数

2.1.表的创建以及删除

// 表的创建以及删除
SeqList *createSeqList(int n);                  // 创造一个表并初始化void releaseSeqList(SeqList *seqList);          // 释放掉表头以及表内的数据

 2.2.扩容函数

// 辅助函数
int enLargerSeq(SeqList *seqList);                  // 扩容函数

2.3.向表中插入元素

// 三种插入方式
int pushBackSeq(SeqList *seqList, Element val);         // 往尾部插入一个元素int headInsertSeq(SeqList *seqList, Element val);       // 往头部插入一个元素int insertSeq(SeqList *seqList, int pos, Element val);  // 按指定值来插入元素

2.4.表的展示以及查找

// 展示以及查找
void showSeqList(SeqList *seqList);                // 遍历并显示数据int findSeq(SeqList *seqList, Element val);        // 按值查找

2.5.删除表中的元素

// 三种方式删除
int deleteSpeSeq(SeqList *seqList, Element val);   // 删除特定值的元素int deleteHeadSeq(SeqList *seqList);               // 删除首元素int deleteTailSeq(SeqList *seqList);               // 删除尾元素

3.实现函数的代码

3.1.createSeqList函数的实现

函数定义:
SeqList *createSeqList(int n);                  // 创造一个表并初始化

函数功能:
该函数用于创建一个长度为n的顺序表,并返回指向该顺序表的指针

实现思路
a.申请表头空间b.申请表内元素的空间c.初始化 len(length 长度) 和 cap(capacity 容量)d.对申请的空间进行检查,如果申请空间失败,则需要返回NULL

具体实现代码:
SeqList *createSeqList(int n) {SeqList *seqList;seqList = (SeqList *)malloc(sizeof(SeqList));               //申请表头if (seqList == NULL){printf("Malloc seqlist failed\n");return NULL;}seqList->data = (Element *) malloc(sizeof(Element) * n);    //申请空间if (seqList->data == NULL){printf("Malloc data failed");return NULL;}seqList->len = 0;seqList->cap = n;return seqList;
}

测试代码:
int main() {SeqList *list = createSeqList(10);if (list == NULL) {printf("创建顺序表失败\n");return 1;}printf("顺序表创建成功\n");free(list->data);free(list);return 0;
}

测试结果:

3.2 releaseSeqList函数的实现

函数定义:
void releaseSeqList(SeqList *seqList);          // 释放掉表头以及表内的数据

函数功能:
该函数用于释放一个顺序表所占用的内存空间,防止内存泄漏

实现思路:
a.先判断表头再判断数据域是否为空b.如果数据域不为空,则释放掉表内的数据域空间c.释放掉表头空间

 具体实现代码:
void releaseSeqList(SeqList *seqList) {if (seqList){if (seqList->data){free(seqList->data);}free(seqList);printf("Release success!\n");}
}

测试代码:
int main() {SeqList *list = createSeqList(10);if (list == NULL) {printf("创建顺序表失败\n");return 1;}printf("顺序表创建成功\n");releaseSeqList(list);  // 释放顺序表return 0;
}

测试结果:

3.3 enLargerSeq 函数的实现

函数定义:
int enLargerSeq(SeqList *seqList);                  // 扩容函数

函数功能:
该函数用于对顺序表进行扩容,将顺序表的大小扩展为原来的两倍

实现思路:
a.先申请一个新空间 tmp,新空间的大小为原来空间大小(seqList->len / seqList->cap)的两倍
b.将原来空间的值通过 for 循环赋值给新空间
c.释放掉原来表头指向的空间 seqList->data
d.将表头的 seqList->data 指向新申请的空间 tmp
e.将 seqList->cap 大小变为原来的两倍

具体实现代码:
int enLargerSeq(SeqList *seqList) {Element *tmp = (Element *) malloc(sizeof (Element) * 2 * seqList->cap);if (!tmp){printf("Enlarger element failed!\n");return -1;}for (int i = 0; i < seqList->len; i++){tmp[i] = seqList->data[i];}free(seqList->data);    // 这两句是否有先后?seqList->data = tmp;    // 有先后,如果调换顺序就会先指向新的内存空间,然后再释放老的内存空间,此时老的内存空间已经找不到了,会发生内存泄露seqList->cap *= 2;printf("Enlarge success!\n");return 0;
}

测试代码:
int main(){SeqList *list = createSeqList(5);for (int i = 0; i < 5; i++){pushBackSeq(list, i);}pushBackSeq(list,666);showSeqList(list);printf("%d", list->cap);return 0;
}

测试结果:

3.4 showSeqList && findSeq 函数的实现

函数定义:
void showSeqList(SeqList *seqList);                // 遍历并显示数据int findSeq(SeqList *seqList, Element val);        // 按值查找

函数功能:

1.showSeqList 函数

该函数用于遍历并显示顺序表中的所有数据

2.findSeq 函数 

该函数用于在顺序表中查找指定的值,并返回该值的索引。如果未找到,则返回 -1

实现思路:

1.showSeqList 函数

a.首先判断传入的表是否为空
b.使用 for 循环遍历整个表并打印数据

2.findSeq 函数

a.判断传染的表是否为空且表的长度是否合法(seqList->len > 0)
b.使用for循环遍历表,如果找到了val就直接返回该数的下标
c.如果没找到,打印提示信息,返回-1

具体实现代码:
// showSeqList 函数
void showSeqList(SeqList *seqList) {if (seqList == NULL || seqList->data == NULL){printf("SeqList is null.Show error\n");return;}for (int i = 0; i < seqList->len; i++){printf("%d ", seqList->data[i]);}printf("\n");
}// findSeq 函数
int findSeq(SeqList *seqList, Element val) {if (!seqList || !seqList->data || seqList->len <= 0){printf("SeqList is null!\n");return -1;}for (int i = 0; i < seqList->len; i++){if (seqList->data[i] == val){return i;}}printf("Find value error!\n");return -1;
}

测试代码:
int main(){SeqList *list = createSeqList(5);for (int i = 0; i < 5; i++){pushBackSeq(list, i);}showSeqList(list);int index1 = findSeq(list, 666);int index2 = findSeq(list,0);printf("%d\n", index1);printf("%d\n", index2);releaseSeqList(list);return 0;
}

测试结果:

3.4 pushBackSeq && headInsertSeq && insertSeq 函数的实现

函数定义:
int pushBackSeq(SeqList *seqList, Element val);         // 往尾部插入一个元素int headInsertSeq(SeqList *seqList, Element val);       // 往头部插入一个元素int insertSeq(SeqList *seqList, int pos, Element val);  // 按指定位置来插入元素

函数功能:
1.pushBackSeq 函数
在顺序表尾部插入一个元素
2.headInsertSeq 函数
在顺序表头部插入一个元素
3.insertSeq 函数
在顺序表指定位置插入一个元素

实现思路:

1.pushBackSeq 函数

a.判断传入的链表以及数据域是否为空b.判断当前元素是否到达空间上限,如果是则需要扩容c.往 seqList->len 的位置放入元素d.seqList->len++

 2.headInsertSeq 函数

a.判断传入的链表以及数据域是否为空b.判断当前元素是否到达空间上限,如果是则需要扩容c.从第 1 个元素开始,依次往后移动元素d.往下标为 0 的位置放入元素e.seqList->len++

3.insertSeq 函数

a.判断传入的链表以及数据域是否为空b.判断当前元素是否到达空间上限,如果是则需要扩容c.从第 seqList->len-1 个元素开始,直到第 pos 个元素(包含),从后往前移动元素d.往下标为 pos 的位置放入元素e.seqList->len++

具体实现代码:

1.pushBackSeq 函数

// pushBackSeq 函数
int pushBackSeq(SeqList *seqList, Element val) {if (!seqList || !seqList->data){printf("Seqlist is null");return -1;}if (seqList->len >= seqList->cap){printf("Insertion overflow. Consider enlarging the structure!\n");if (enLargerSeq(seqList) == -1){printf("Enlarge failed!\n");return -1;}}seqList->data[seqList->len] = val;seqList->len++;return 0;
}

  2.headInsertSeq 函数

// headInsertSeq 函数
int headInsertSeq(SeqList *seqList, Element val) {if (!seqList || !seqList->data){printf("Seqlist is null");return -1;}if (seqList->len >= seqList->cap){printf("Insertion overflow. Consider enlarging the structure!\n");if (enLargerSeq(seqList) == -1){printf("Enlarge failed!\n");return -1;}}for (int i = seqList->len; i > 0; i--) {        // 核心移动逻辑seqList->data[i] = seqList->data[i-1];}seqList->data[0] = val;seqList->len++;return 0;
}

 3.insertSeq 函数

// insertSeq 函数
int insertSeq(SeqList *seqList, int pos, Element val) {if (!seqList || !seqList->data){printf("Seqlist is null");return -1;}// 为什么是 > seqList->len,而不是 > seqList->cap?// 顺序表是一种线性数据结构,它要求元素在内存中连续存储。这意味着元素之间不能有空隙,必须紧密排列// 使用 len 而不是 cap 来确定插入位置,可以保证顺序表中的元素始终保持连续存储,这是顺序表的核心特征if (pos < 0 || pos > seqList->len){printf("Insert value out of bounds\n");return -1;}if (seqList->len >= seqList->cap){printf("Insertion overflow. Consider enlarging the structure!\n");if (enLargerSeq(seqList) == -1){printf("Enlarge failed!\n");return -1;}}for (int i = seqList->len-1; i >= pos; i--){    // 核心移动逻辑seqList->data[i+1] = seqList->data[i];}seqList->data[pos] = val;seqList->len++;return 0;
}

测试代码:
int main(){SeqList *list = createSeqList(5);for (int i = 0; i < 5; i++){pushBackSeq(list, i);}showSeqList(list);insertSeq(list, 5, 111);      // 任意位置插入showSeqList(list);insertSeq(list, 0, 222);      // 任意位置插入showSeqList(list);insertSeq(list, 999, 333);    // 任意位置插入showSeqList(list);printf("\n");headInsertSeq(list, 888);     // 头插法showSeqList(list);printf("\n");pushBackSeq(list, 666);       // 尾插法showSeqList(list);releaseSeqList(list);return 0;
}

测试结果:

3.5 deleteSpeSeq && deleteHeadSeq && deleteTailSeq 函数的实现

函数定义:
int deleteSpeSeq(SeqList *seqList, Element val);   // 删除特定值的元素int deleteHeadSeq(SeqList *seqList);               // 删除首元素int deleteTailSeq(SeqList *seqList);               // 删除尾元素

函数功能:

1.deleteSpeSeq 函数

该函数用于在顺序表中删除指定值的元素

2. deleteHeadSeq 函数  

该函数用于删除顺序表中的首元素

 3.deleteTailSeq 函数 

该函数用于删除顺序表中的尾元素

实现思路:

1.deleteSpeSeq 函数

a.判断传入的表是否为空
b.调用 findSeq 函数,判断要查找的值是否在表中
c.如果不在表中,则返回错误标志
d.从 pos+1 的位置开始,从后往前覆盖元素
e.seqList->len--

2. deleteHeadSeq 函数 

a.判断传入的表是否为空
b.判断表内是否有元素
c.从第二个元素(索引为1)开始,从后往前进行覆盖
d.seqList->len--

3.deleteTailSeq 函数 

a.判断传入的表是否为空
b.判断表内是否有元素
d.seqList->len--

具体实现代码:

1.deleteSpeSeq 函数

int deleteSpeSeq(SeqList *seqList, Element val) {if (!seqList || !seqList->data){printf("Seqlist is null. Delete failed!\n");return -1;}int pos = findSeq(seqList, val);if (pos == -1){printf("Delete value error!\n");return -1;}for (int i = pos + 1; i < seqList->len; i++){seqList->data[i - 1] = seqList->data[i];}/*for (int i = pos; i < seqList->len; i++){ // 第二种写法可能会有溢出的风险seqList->data[i] = seqList->data[i + 1];}*/seqList->len--;return 0;
}

2. deleteHeadSeq 函数

int deleteHeadSeq(SeqList *seqList) {if (!seqList || !seqList->data){printf("Seqlist is null. Delete failed!\n");return -1;}if (seqList->len <= 0){printf("Delete head value failed!");return -1;}for (int i = 1; i < seqList->len; i++){seqList->data[i-1] = seqList->data[i];}seqList->len--;return 0;
}

3.deleteTailSeq 函数

int deleteTailSeq(SeqList *seqList) {if (!seqList || !seqList->data){printf("Seqlist is null. Delete failed!\n");return -1;}if (seqList->len <= 0){printf("Delete tail value failed!");return -1;}seqList->len--;return 0;
}

测试代码:
int main(){SeqList *list = createSeqList(5);for (int i = 0; i < 5; i++){pushBackSeq(list, i);}deleteHeadSeq(list);showSeqList(list);deleteTailSeq(list);showSeqList(list);deleteSpeSeq(list,999);showSeqList(list);deleteSpeSeq(list,1);showSeqList(list);releaseSeqList(list);return 0;
}

测试结果:

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

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

相关文章

C++客户端Qt开发——常用控件(容器类控件)

6.容器类控件 ①GroupBox 带标题分组框 属性 说明 title 分组框的标题 alignment 分组框内部内容的对齐方式 flat 是否是"扁平"模式 checkable 是否可选择 设为true,则在title前方会多出一个可勾选的部分. check 描述分组框的选择状态&#xff08;前提…

数据结构(5.1)——树的性质

结点数总度数1 结点的度——结点有几个孩子(分支) 度为m的树、m叉树的区别 度为m的树第i层至多有 个结点(i>1) 高度为h的m叉树至多有 个结点 高度为h的m叉树至少有h个结点 、高度为h&#xff0c;度为m叉树至多有hm-1个结点 具有n个结点的m叉树的最小高度为 总结

通过角点进行水果的果梗检测一种新方法

一、前言 在前面的《数字图像处理与机器视觉》案例一&#xff08;库尔勒香梨果梗提取和测量&#xff09;中主要使用数学形态学的方法进行果梗提取&#xff0c;下面给出一种提取果梗的新思路。 众所周知&#xff0c;一般果梗和果实在边缘处角度有较大突变&#xff0c;可以通过合…

探索WebKit的CSS列表与标记:美化列表的艺术

探索WebKit的CSS列表与标记&#xff1a;美化列表的艺术 CSS列表和标记是网页设计中用于增强列表展示效果的重要工具。WebKit&#xff0c;作为多种现代浏览器的内核&#xff0c;包括Safari、QQ浏览器等&#xff0c;提供了对CSS列表和标记的广泛支持。本文将深入探讨WebKit对CSS…

spring security源码追踪理解(一)

一、前言 近期看了spring security相关的介绍&#xff0c;再加上项目所用若依框架的底层安全模块也是spring security&#xff0c;所以想从源码的角度加深下对该安全模块的理解&#xff08;看源码之前&#xff0c;我们要先有个意识&#xff0c;那就是spring security安全模块主…

Solus Linux简介

以下是学习笔记&#xff0c;具体详实的内容请参考官网&#xff1a;Home | Solus Solus Linux 是一个独立的 Linux 发行版&#xff0c;它以其现代的设计、优化的性能和友好的用户体验而著称。以下是一些关于 Solus Linux 的最新动向和特点&#xff1a; 1. **最新版本发布**&a…

第122天:内网安全-域信息收集应用网络凭据CS 插件AdfindBloodHound

目录 前置知识 背景和思路 判断是否在域内 案例一&#xff1a;架构信息类收集-网络&用户&域控等 案例二&#xff1a;自动化工具探针-插件&Adfind&BloodHound Adfind(域信息收集工具) ​BloodHound&#xff08;自动化域渗透工具&#xff09; 前置知识 本…

计算机视觉10 总结

全卷积网络&#xff08;FCN&#xff09;是计算机视觉中用于处理图像任务的重要网络架构。 核心要点&#xff1a; 与传统 CNN 不同&#xff0c;FCN 将最后的全连接层替换为卷积层&#xff0c;从而能够处理任意尺寸的输入图像&#xff0c;并保留了空间信息。优点包括可处理不同大…

java基础万字笔记

前言 此篇文章为本人在初学java时所记录的java基础的笔记&#xff0c;其中全面记录了java的基础知识点以及自己的一些理解和要注意的点。由于该笔记是边学边记录而成&#xff0c;所以基本很多模块内都会有一些我本人后期记录的知识穿插进去&#xff0c;导致一些模块内的内容并…

搭建个人智能家居 7 - 空气颗粒物检测

搭建个人智能家居 7 - 空气颗粒物检测 前言说明PMS5003ESPHomeHomeAssistant结束 前言 到目前为止&#xff0c;我们这个智能家居系统添加了4个外设&#xff0c;分别是&#xff1a;LED灯、RGB灯、DHT11温度传感器和SGP30。今天继续添加环境测量类传感器“PMS5003空气颗粒物检测…

Django获取request请求中的参数

支持 post put json_str request.body # 属性获取最原始的请求体数据 json_dict json.loads(json_str)# 将原始数据转成字典格式 json_dict.get("key", "默认值") # 获取数据参考 https://blog.csdn.net/user_san/article/details/109654028

Windows FFmpeg 开发环境搭建

FFmpeg 开发环境搭建 FFmpeg命令行环境搭建使用FFmpeg官方编译的库Windows编译FFmpeg1. 下载[msys2](https://www.msys2.org/#installation)2. 安装完成之后,将安装⽬录下的msys2_shell.cmd中注释掉的 rem set3. 修改pacman 镜像源并安装依赖4. 下载并编译源码 FFmpeg命令行环境…

39、PHP 实现二叉树的下一个结点(含源码)

题目&#xff1a; PHP 实现二叉树的下一个结点 描述&#xff1a; 给定一个二叉树和其中的一个结点&#xff0c;请找出中序遍历顺序的下一个结点并且返回。 注意&#xff0c;树中的结点不仅包含左右子结点&#xff0c;同时包含指向父结点的指针。 <?php /*class TreeLinkN…

vite+vue3项目初始化搭建

vitevue3项目初始化搭建 "nodejs": v18.19.0 "pnpm": 8.15.0 "vue": v3.4.21 "vite": v5.2.01.创建项目 Vite中文官网 pnpm create vitelatest项目名字&#xff1a;gd_web 选择框架&#xff1a;Vue3 选择语言&#xff1a;JavaScrip…

基于springboot和mybatis的RealWorld后端项目实战三之添加swagger

pom.xml添加依赖 <dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger2</artifactId><version>2.9.2</version></dependency><dependency><groupId>io.springfox</groupId><arti…

解决网页中的 video 标签在移动端浏览器(如百度访问网页)视频脱离文档流播放问题

问题现象 部分浏览器视频脱离文档流&#xff0c;滚动时&#xff0c;视频是悬浮出来&#xff0c;在顶部播放 解决方案 添加下列属性&#xff0c;可解决大部分浏览器的脱离文档流的问题 <videowebkit-playsinline""playsInlinex5-playsinlinet7-video-player-t…

JS【详解】真值 vs 假值(虚值 / falsy 值)

假值&#xff08;虚值 / falsy 值&#xff09; 转换为布尔类型后&#xff0c;结果为 false 的数据即假值&#xff0c;共 7 种 falsenullundefined0-0NaN空字符串 —— "" 或 或 【实战】删除数组中的假值 let list [null, 1, undefined, 2, NaN, 3]; let resul…

AI辅助自动驾驶技术在2024年的发展与趋势

文章目录 综述 2024 年 AI 辅助研发趋势 第一章&#xff1a;引言 1.1 背景介绍 1.2 AI在自动驾驶中的地位和作用 1.3 2024年自动驾驶技术的现状 1.4 论文结构 第二章&#xff1a;AI技术在自动驾驶中的应用 2.1 深度学习算法在自动驾驶中的应用 2.2 数据分析与模式识别…

谷类大米农业行业网站源码系统 带完整的安装代码包以及搭建部署教程

系统概述 在当今数字化时代&#xff0c;农业行业也逐渐迈向信息化、智能化。为了满足谷类大米农业行业的信息化需求&#xff0c;我们推出了一款专为该行业设计的网站源码系统。该系统不仅具备丰富的行业特色功能&#xff0c;而且提供了完整的安装代码包以及详细的搭建部署教程…

GitHub热门开源项目-2024版

文章目录 awesome系列sindresorhus/awesomeawesome-selfhosted/awesome-selfhostedvinta/awesome-pythonavelino/awesome-gof/awesome-chatgpt-promptsHack-with-Github/Awesome-HackingFortAwesome/Font-Awesomejaywcjlove/awesome-macvuejs/awesome-vueDopplerHQ/awesome-int…