数据结构:去发现顺序表的魅力所在

✨✨小新课堂开课了,欢迎欢迎~✨✨

🎈🎈养成好习惯,先赞后看哦~🎈🎈

所属专栏:http://t.csdnimg.cn/oHJAK(数据结构与算法)

小新的主页:编程版小新-CSDN博客

1.什么是顺序表

顺序表的底层是数组,但它提供了很多现成的方法,开箱即用,就成了顺序表。简单来理解顺序表其实就是数组的升级版。顺序在物理结构上不一定连续,但在逻辑结构上是连续的,可以抽象成一个直线 。

2.顺序表的分类

顺序表可以分为静态顺序表和动态顺序表。

2.1顺序表的定义

静态顺序表


#define N 100struct SeqList
{int arr[N];int size;//有效数据个数
};

动态顺序表

typedef int SLDataType;//为了方便更改类型
typedef struct SeqList
{SLDataType* arr;int size;//有效数据个数int capacity;//空间大小
}SL;

静态顺序表的数组是定长的,给小了不够用,给大了浪费空间,而动态顺序表是可以动态增容的,相对于静态顺序表更加的灵活和节省空间,所以也更推荐使用动态顺序表。

3.顺序表的功能

1.顺序表的初始化

2.对顺序表进行尾插(在末尾处插入数据)

3.对顺序表进行尾删(删除末尾处的数据)

4.对顺序表进行头插(在开始位置插入数据)

5.对顺序表进行头删(删除在起始位置的数据)

6.在指定位置之前插入数据

7.删除指定位置的数据

8.打印顺序表

9.查找顺序表

10.修改顺序表

11.销毁顺序表

4.顺序表功能的实现

4.1顺序表的初始化

//顺序表的初始化
void SLInit(SL* ps)//传址调用
{ps->arr = NULL;ps->size = ps->capacity = 0;
}

易错点:这里一定要采用传址调用,因为采用传值调用的话,形参只是对实参的一份临时拷贝,出了{}以后就被销毁了。

4.2顺序表的尾插

在说明顺序表的尾插之前,我们要先想一个问题,我们既然要插入数据,就要考虑空间够不够的问题,所以数据在进行插入之前要检查空间够不够。

//检查是否用足够的空间
void SLCheck(SL* ps)
{if (ps->size == ps->capacity)//空间不够{//申请空间//三目操作符int newcapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;SLDataType* tmp = (SLDataType*)realloc(ps->arr, newcapacity * sizeof(SLDataType));//需要申请多大的空间if (tmp == NULL){perror("realloc fail");return;}//申请成功ps->arr = tmp;ps->capacity = newcapacity;}}

动态增容的时候,一般是成倍的扩增,采用2倍扩增是比较合适的。

这里大家可能会有疑问,这样开辟空间不会浪费空间吗?

答案是会的,但是这样浪费的空间相对于静态开辟的空间好一些。

在开辟空间的时候为什么要*sizeof(类型),因为单位是字节,要*sizeof(类型)才能得出真正所需要的空间大小。

判断了空间够不够之后,我们看一看如何进行尾插吧。

//顺序表的尾插
void SLPushBack(SL* ps, SLDataType x)
{assert(ps);//插入之前要检查是否有空间SLCheck(ps);//插入ps->arr[ps->size++] = x;//细节之后置++
}

后置++,在这里使用的是真的很不错。 

 4.3顺序表的尾删

//顺序表的尾删
void SLPopBack(SL* ps)
{assert(ps);assert(ps->size);//顺序表不能为空--ps->size;
}

4.4顺序表的头插

//头插
void SLPushFront(SL* ps, SLDataType x)
{assert(ps);//插入之前要检查是否有足够的空间SLCheck(ps);//先让顺序表中已有的数据整体往后移动一位for (int i = ps->size; i > 0; i--){ps->arr[i] = ps->arr[i - 1];}ps->arr[0] = x;ps->size++;//不要忘记++
}

这里之所以是从后往前移动是为了避免数据被覆盖。

4.5 顺序表的头删

//顺序表的头删
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--;
}

4.6在指定位置之前插入数据


//在指定位置之前插入数据
void SLInsert(SL* ps, int pos, SLDataType x)
{assert(ps);assert(pos >= 0 && pos <= ps->size);//插入之前要检查空间够不够SLCheck(ps);//先让pos及其之后的数据整体往后挪动一位for (int i = ps->size; i > pos; i--){ps->arr[i] = ps->arr[i - 1];//如果不知道结束条件是什么就可以用最后一次挪动去推//ps->arr[pos+1]=ps->arr[pos]}ps->arr[pos] = x;ps->size++;
}

4.7在指定位置删除数据

//删除指定位置的数据
void SLErase(SL* ps, int pos)
{assert(ps);assert(pos >= 0 && pos < ps->size);//让pos之后的数据整体往前挪动一位for (int i = pos; i < ps->size-1; i++){ps->arr[i] = ps->arr[i + 1];}ps->size--;}

4.8打印顺序表

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

4.9查找顺序表

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

4.10修改顺序表

//修改指定位置的数据
void SeqListModify(SL* ps, int pos, SLDataType x)
{assert(ps);  //断言assert(ps->size > 0);  //顺序表不能为空assert(pos >= 0 && pos < ps->size);  //检查pos下标的合法性ps->arr[pos] = x;  //修改pos下标处对应的数据
}

4.11销毁顺序表

//顺序表的销毁
void SLDestroy(SL* ps)
{if (ps->arr != NULL)//ps->arr{free(ps->arr);}ps->arr = NULL;//避免访问野指针ps->size = ps->capacity = 0;
}

5.完整代码

5.1SeqList.c

#include"SeqList.h"
//顺序表的初始化
void SLInit(SL* ps)//传址调用
{ps->arr = NULL;ps->size = ps->capacity = 0;
}
//顺序表的销毁
void SLDestroy(SL* ps)
{if (ps->arr != NULL)//ps->arr{free(ps->arr);}ps->arr = NULL;//避免访问野指针ps->size = ps->capacity = 0;
}//检查是否用足够的空间
void SLCheck(SL* ps)
{if (ps->size == ps->capacity)//空间不够{//申请空间//三目操作符int newcapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;//少了等号。一个是赋值SLDataType* tmp = (SLDataType*)realloc(ps->arr, newcapacity * sizeof(SLDataType));//需要申请多大的空间if (tmp == NULL){perror("realloc fail");return;}//申请成功ps->arr = tmp;ps->capacity = newcapacity;}}//打印顺序表
void SLPrint(SL ps)
{for (int i = 0; i < ps.size; i++){printf("%d ", ps.arr[i]);}printf("\n");
}//顺序表的尾插
void SLPushBack(SL* ps, SLDataType x)
{assert(ps);//插入之前要检查是否有空间SLCheck(ps);//插入ps->arr[ps->size++] = x;//细节之后置++
}//头插
void SLPushFront(SL* ps, SLDataType x)
{assert(ps);//插入之前要检查是否有足够的空间SLCheck(ps);//先让顺序表中已有的数据整体往后移动一位for (int i = ps->size; i > 0; i--){ps->arr[i] = ps->arr[i - 1];}ps->arr[0] = x;ps->size++;//不要忘记++
}//在指定位置之前插入数据
void SLInsert(SL* ps, int pos, SLDataType x)
{assert(ps);assert(pos >= 0 && pos <= ps->size);//插入之前要检查空间够不够SLCheck(ps);//先让pos及其之后的数据整体往后挪动一位for (int i = ps->size; i > pos; i--){ps->arr[i] = ps->arr[i - 1];//ps->arr[pos+1]=ps->arr[pos]}ps->arr[pos] = x;ps->size++;
}//删除指定位置的数据
void SLErase(SL* ps, int pos)
{assert(ps);assert(pos >= 0 && pos < ps->size);//让pos之后的数据整体往前挪动一位for (int i = pos; i< ps->size - 1; i++){ps->arr[i] = ps->arr[i + 1];}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 SeqListModify(SL* ps, int pos, SLDataType x)
{assert(ps);  //断言assert(ps->size > 0);  //顺序表不能为空assert(pos >= 0 && pos < ps->size);  //检查pos下标的合法性ps->arr[pos] = x;  //修改pos下标处对应的数据
}//查找指定数据
int SLFind(SL* ps, SLDataType x)
{assert(ps);for (int i = 0; i < ps->size; i++){if (ps->arr[i] == x){//找到了return i;//返回下标}}//没有找到return -1;}

5.2SeqList.h

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
//定义顺序表//静态顺序表
//#define N 100
//
//struct SeqList
//{
//	int arr[N];
//	int size;//有效数据个数
//};//动态顺序表
typedef int SLDataType;
typedef struct SeqList
{SLDataType* arr;int size;//有效数据个数int capacity;//空间大小
}SL;//顺序表的初始化
void SLInit(SL* ps);//顺序表的销毁
void SLDestroy(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);//打印顺序表
void SLPrint(SL ps);//查找数据
int SLFind(SL* ps, SLDataType x);//修改指定位置的数据
void SeqListModify(SL* ps, int pos, SLDataType x);

下课了~

别忘了下次再来哦

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

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

相关文章

Docker入门实战教程

文章目录 Docker引擎的安装Docker比vm虚拟机快 Docker常用命令帮助启动类命令镜像命令docker imagesdocker searchdocker pulldocker system dfdocker rmi 容器命令redis前台交互式启动redis后台守护式启动Nginx容器运行ubuntu交互式运行tomcat交互式运行对外暴露访问端口 Dock…

Linux的内存管理子系统

大家好&#xff0c;今天给大家介绍Linux的内存管理子系统&#xff0c;文章末尾附有分享大家一个资料包&#xff0c;差不多150多G。里面学习内容、面经、项目都比较新也比较全&#xff01;可进群免费领取。 Linux的内存管理子系统是Linux内核中一个非常重要且复杂的子系统&#…

防火墙操作!

当小编在Linux服务器上部署好程序以后&#xff0c;但是输入URL出现下述情况&#xff0c;原来是防火墙的原因&#xff01;&#xff01; 下面是一些防火墙操作&#xff01; 为保证系统安全&#xff0c;服务器的防火墙不建议关闭&#xff01;&#xff01; 但是&#xff0c;我们可…

【网络安全】WebPack源码(前端源码)泄露 + jsmap文件还原

前言 webpack是一个JavaScript应用程序的静态资源打包器。它构建一个依赖关系图&#xff0c;其中包含应用程序需要的每个模块&#xff0c;然后将所有这些模块打包成一个或多个bundle。大部分Vue等项目应用会使用webpack进行打包&#xff0c;使用webpack打包应用程序会在网站js…

20240327-1-评测指标面试题

评测指标面试题 metric主要用来评测机器学习模型的好坏程度,不同的任务应该选择不同的评价指标,分类,回归和排序问题应该选择不同的评价函数. 不同的问题应该不同对待,即使都是分类问题也不应该唯评价函数论,不同问题不同分析. 回归(Regression) 平均绝对误差(MAE) 平均绝对…

CMake 学习笔记2

其他很好的总结 CMake教程系列-01-最小配置示例 - 知乎 CMake 保姆级教程&#xff08;上&#xff09; | 爱编程的大丙 10-补充(完结)_哔哩哔哩_bilibili 1、基本关键字 SET命令的补充 &#xff08;1&#xff09;SET命令设置执行标准 #增加-stdc11 set(CMAKE_CXX_STANDARD…

Terminal 美化

摘自&#xff1a;Mac 系统终端美化与 ZSH 多设备配置同步共享 个人对 iTerm2 等第三方终端工具不太感冒&#xff0c;一直在用系统内置终端。 相比之下&#xff0c;系统自带的 Terminal 可谓是简陋啊。 安装了 Oh My Zsh&#xff0c;加上一些插件&#xff0c;感觉还行。 再调…

如何防止软件过度封装和抽象?

一、合适的软件架构 构建可读性强、高内聚、低耦合的软件架构是软件工程中的重要原则&#xff0c;这有助于提高代码的维护性、扩展性和复用性。以下是一些实践方法&#xff1a; 1. **模块化设计**&#xff1a;将系统划分为一系列职责单一、功能明确的模块或组件&#xff0c;每…

ELK企业级日志分析系统以及多种部署

目录 ELK简介 ELK简介 ELK平台是一套完整的日志集中处理解决方案&#xff0c;将 ElasticSearch、Logstash 和 Kiabana 三个开源工具配合使用&#xff0c; 完成更强大的用户对日志的查询、排序、统计需求。 ●ElasticSearch&#xff1a;是基于Lucene&#xff08;一个全文检索引…

windows应急中的快捷键

windows应急中的快捷键 应急的时候&#xff0c;快捷键很重要&#xff0c;记录一下windows主机排查需要用到的快捷键 windows快捷键 appwiz.cpl 是打开安装面板 程序和功能 控制面板程序和功能 搜索程序和功能 控制而板主页 卸载或更改程序 若要卸酸程序,请从列表中将其…

Python工程师面试高频题:return 和 yield之间到底有啥区别?

在编程语言 Python 中&#xff0c;yield 和 return 是两个在函数中用于返回值的关键字&#xff0c;但它们在功能和使用场景上有着本质的区别。理解这两者的区别&#xff0c;对于编写更高效、更灵活的 Python 代码至关重要。 看图说话 首先我们来看下面这张图片&#xff0c;该…

跨平台桌面应用 Electron 入门学习

本文章主要为该视频的学习笔记&#xff0c;如果侵权会速删。 Electron 01 课程介绍_哔哩哔哩_bilibiliElectron 01 课程介绍, 视频播放量 3046、弹幕量 0、点赞数 75、投硬币枚数 43、收藏人数 179、转发人数 2, 视频作者 极客丶张德龙, 作者简介 当你的能力还不足以撑起自己的…

使用UDP实现TCP的功能,会带来什么好处?

比较孤陋寡闻&#xff0c;只知道QUIC TCPQUIC握手延迟TCP需要三次握手TLS握手三次握手TLS握手放在一起&#xff0c;实现0RTT头阻塞问题TCP丢失保文&#xff0c;会影响所有的应用数据包基于UDP封装传输层Stream&#xff0c;Stream内部保序&#xff0c;Stream之间不存在相互影响…

Coursera吴恩达《深度学习》课程总结(全)

这里有Coursera吴恩达《深度学习》课程的完整学习笔记&#xff0c;一共5门课&#xff1a;《神经网络和深度学习》、《改善深层神经网络》、《结构化机器学习项目》、《卷积神经网络》和《序列模型》&#xff0c; 第一门课&#xff1a;神经网络和深度学习基础&#xff0c;介绍一…

每日一题(leetcode238):除自身以外数组的乘积--前缀和

不进阶是创建两个数组&#xff1a; class Solution { public:vector<int> productExceptSelf(vector<int>& nums) {int nnums.size();vector<int> left(n);vector<int> right(n);int mul1;for(int i0;i<n;i){mul*nums[i];left[i]mul;}mul1;for…

攻防世界12-baby_web

12-baby_web 题目说想想初始页面是哪个&#xff0c;一般都是index.php&#xff0c;然后如题分析即可。 我们在链接后面拼接上/index.php&#xff0c;返回后发现界面又回到了1.php&#xff0c;有可能是重定向。 我们点击检查-网络&#xff0c;发现没有index的请求&#xff0c;…

编曲知识18:EQ均衡器 齿音处理 呼吸音处理 口水音处理

EQ均衡器 齿音处理 呼吸音处理 口水音处理小鹅通-专注内容付费的技术服务商https://app8epdhy0u9502.pc.xiaoe-tech.com/live_pc/l_66151c90e4b092c1187ac699?course_id=course_2XLKtQnQx9GrQHac7OPmHD9tqbv 均衡器 均衡器 Equalizer(简称EQ) 人耳接受频率:20hz—20khz …

系统架构最佳实践 -- API网关架构设计

目录 1.什么是API网关&#xff1f; 2.API网关的核心功能 3.架构设计原则 4.API网关的实现方式 5.常见的API网关工具和框架 6.实际案例分析 API网关是现代微服务架构中的重要组件&#xff0c;它充当了前端和后端微服务之间的中介。本文将介绍API网关的架构设计原则和实现方…

Leetcode 剑指 Offer II 073.爱吃香蕉的狒狒

题目难度: 中等 原题链接 今天继续更新 Leetcode 的剑指 Offer&#xff08;专项突击版&#xff09;系列, 大家在公众号 算法精选 里回复 剑指offer2 就能看到该系列当前连载的所有文章了, 记得关注哦~ 题目描述 狒狒喜欢吃香蕉。这里有 N 堆香蕉&#xff0c;第 i 堆中有 piles…

华为海思数字芯片设计笔试第二套

1.声明 下面的题目作答都是自己认为正确的答案&#xff0c;并非官方答案&#xff0c;如果有不同的意见&#xff0c;可以评论区交流。 这些题目也是笔者从各个地方收集的&#xff0c;感觉有些题目答案并不正确&#xff0c;所以在个别题目会给出自己的见解&#xff0c;欢迎大家讨…