数据结构第二课 | 顺序表(详解)
前言:Hello!大家好,我是@每天都要敲代码,上次我们讲了数据结构第一课时间复杂度和空间复杂度;不明白的小伙伴可以学习一遍时间复杂度和空间复杂度传送门;今天让我们开始一起学习数据结构第二课啦-----线性表;在学习线性表之前,我们要先弄清楚它的概念,下面让我们一起来看看吧!
概念:
线性表:线性表是n个具有相同特性的数据元素的有限序列。线性表是一种在实际中广泛
使用的数据结构,常见的线性表:顺序表、链表、栈、队列、字符串....
解释:线性表在逻辑上是线性结构,也就是连续的一条直线。但是在物理结构上并不一定是
连续的,线性表在物理上存储时,通常以【数组】和【链式结构】(链表)的形式存储
数组空间是连续的,链表空间是不连续的。顺序表实现:顺序表是用一段【物理地址连续】的存储单元【依次存储数据元素】的线性结构,一般情况下采用数组存储。在数组上完成数据的增删改查。
顺序表一般可以分为:
1.静态顺序表:适应定长数组存储。
2.动态顺序表:使用动态开辟的数组存储
目录
静态顺序表:
动态顺序表:
1.先创建顺序表:struct SqList
2.进行初始化:SqListInit
3.打印函数:SqListPrint
4.尾插函数:SqListPushBack
扩容函数:SqListExpasion
5.头插函数:SqListPushFront
6.尾删函数 SqListPopBack
7.头删函数 SqListPopFront
8.修改:SqListModify
查找:SqListFind
9.任意位置插入:SqListInsert
10.任意位置删除:SqListDelete
11.销毁:SqListDestory
所有具体代码:
补充题目1: 原地移除元素
补充题目2:合并两个有序数组
总结:
静态链表的形式很简单,但是容量的大小其实是写死了,不太实用;我们先写出静态链表感受一下吧:
静态顺序表:
我们先对顺序表进行初始化,那么传参怎么办呢?传值还是传址?它要改变原来的数据,当然是传址啦;初始化有两种方法,自己选择一种适合自己使用就可以;
第二步我们就把相对简单的打印函数写出来了;
第三步我们就进行尾插,在插入的时候我们就发现了静态顺序表的弊端,我们首先要进行判满,满了就不能插了,只能手动进行扩容,扩小了造成来回扩容,很麻烦;扩大了又会造成浪费,那么该怎么办?我们不妨写成动态顺序表的形式;所以下面的函数接口我就不在写了;直接写成动态顺序表的形式吧!!!
动态顺序表:
对于动态顺序表我们就把常用的接口函数都写出来吧,虽然稍微有点复杂,不要怕,我们一个一个接口函数来解决:
1.先创建顺序表:struct SqList
包括存储数据的数组arr,用malloc创建出来、有效数据的个数sz、容量capacity;下面一起来实现吧:
2.进行初始化:SqListInit
我们同样也需要传址!!!在写初始化接口函数之前,我们首先要思考,要初始化什么?怎么初始化?
第一种初始化方式:首先我们要肯定要用malloc先动态申请空间,申请空间的大小就是上面定义的宏常量INIT_MAX的大小;值得注意的是malloc开辟空间是以字节为单位开辟的;之后还是把sz的大小初始化为0,容量capacity的大小初始化为INIT_MAX的大小。
第二种初始化方式:当然你也可以像航哥一样,才开始把ps->arr=NULL,ps->sz=0, ps->capacity = 0;我们插入的时候直接realloc进行扩容;这里就需要老铁对malloc和realloc有一定的了解了,我们思考一下,当realloc初始传一个空指针,是不是相当于malloc的作用呢?不妨自己去尝试一下吧!并且写成这种形式,我们在直接用reallo直接扩容之前,要把capacity初始化一个值,不然(倍数*capacity=0)就永远为0了;我们一般扩容为原来的两倍。
下面两种方式的扩容都给出来,选择自己习惯的就好;我是比较偏向第一种方式,所以读这篇博客还是按照第一种初始化方式去理解:
第一种方式初始化:
第二种方式初始化和扩容:
3.打印函数:SqListPrint
同样我们先把相对简单的打印函数写出来,以后需要直接调用这个函数就行:
4.尾插函数:SqListPushBack
扩容函数:SqListExpasion
在尾插之前我们需要先判断是否需要扩容,看ps->sz == ps->capacity;满足我们就需要扩容,而且在哪里插入都需要先判断是否需要扩容;我们不妨封装成一个函数,下面在使用直接调用就行,避免代码冗余;尾插我们在直接插入就行了,不需要数据的移动,很简单:
是否扩容成功呢?我们定义的初始capacity=4,我们不如来多输入几个数来测试一下:
能正常打印出来,说明我们已经扩容成功了!!!
5.头插函数:SqListPushFront
同样在头插之前我们需要先判断是否需要扩容;头插就不像尾插那么简单直接在后面插入数据;头插需要往后移元素,把下标为0的位置留给新插入的数据;那么怎么移动呢?当然是从后面开始移动啦!从前面数据会被覆盖!!!
头插两个数据11、12看运行结果:
正常打印,说明头插成功。
6.尾删函数 SqListPopBack
对于尾删也很简单,直接让ps->sz--访问不到最后一个元素就可以了:
下面我们尾删两个数试试:
发现9、10已经打印不出来了,尾删成功。
7.头删函数 SqListPopFront
对于头删,也要先判断是否为空表;我们同样也要移动元素,从最前面开始,把数据一个个往前移;然后在把ps->sz--就可以啦:这里可以再回过头来去看一下头插函数里面的移动元素和这里头删函数移动元素的区别,对比着学习!!!
下面头删两个元素,打印试试看:
正常删除头两个元素12和11,头删除成功。
8.修改:SqListModify
查找:SqListFind
在修改数据之前,我们肯定要先进行查找,根据数据的下标进行修改操作,所以不妨先封装一个查找的函数SqListFind;根据这个查找函数找下标,然后在传参进行修改:
我们不妨修改一个元素试试,比如:把3改为300:
从这里可以看出,完全是没问题的。
9.任意位置插入:SqListInsert
在任意位置插入;你可以有两种理解,
一种直接给你下标pos,就把数据插入到pos里;比如:我们直接给出下标pos=1的位置插入,这时我们插入之前就要判断pos下标是不是越界;直接用assert(pos<ps->sz)断言就可以。
另外一种理解你可以根据给出的具体数据,调用SqListFind查找函数返回的下标pos,来进行插入;这时返回的下标除了找不到是-1,其它的肯定返回的是合法的值,所以不用越界判断也是可以的。
这里我们只实现第一种理解:
我们不妨在下标为0的元素前面插入100;看运行结果:
从这里可以看出,完全是没问题的。
10.任意位置删除:SqListDelete
同样删除也是和任意位置插入一样,有两种理解;我们还是只实现第一种理解,我们随意给定一个下标就可以删除这个下标的元素:
我们不妨删除下标为1的数据;看运行结果:
从这里可以看出,完全是没问题的,1被删除了。
11.销毁:SqListDestory
所有具体代码:
补充题目1: 原地移除元素
补充题目2:合并两个有序数组
这两道题目是航哥数据结构补充的两道题目;我们在以前的博客里已经做过这两道题目,这里就不在说了,感兴趣的小伙伴,不妨看看我的另外两篇博客,专门详解了这两道题目:传送门1<原地移除元素> 传送门2<合并两个有序数组>
总结:
当然你可以模仿通讯录那样写一个详细的菜单,这里就留给老铁们自己动手写一写!今天的数据结构之顺序表就学完了,希望对您有所收获;等你完全一口气能写出这个顺序表,不妨就尝试把这个当成小项目来写;创建SqList.h:用来存放函数的声明、头文件的引用、结构体的定义、常量的定义等放在这里面;创建SqList.c来写具体函数的实现;创建tect.c来写主函数、以及各个函数的调用等。
数据结构第二课 | 顺序表(详解)相关推荐
- 【数据结构】顺序表详解 | 从零开始步步解读 | 画图理解并调试分析
前言: 本章节将对顺序表的概念进行介绍,着重讲解动态顺序表.对常用的接口函数进行一个个讲解,并进行解析.顺序表讲解部分将从零实现顺序表接口函数,遇到问题我会进行一步步地调试说明,通过对本章的学习不仅能 ...
- 数据结构基础之动态顺序表详解
文章目录 前言 一.动态顺序表的概念 二.顺序表的结构体 三.基本接口 1.SeqListInit(初始化数组) 2.SeqListDestory(销毁数组) 3. SeqListCheckCapac ...
- 【C/C++】静态顺序表详解(附完整源码)
本章内容 1.什么是线性表 2.什么是顺序表 3.静态顺序表结构的定义 4.静态顺序表的函数接口实现 5.静态顺序表的问题及思考 1.什么是线性表 线性表(linear list)是n个具有相同特性的 ...
- 【数据结构】 哈希表 详解
目录 1. 概念 引入 2. 冲突 2.1 概念 2.2 避免 2.3 冲突-避免-哈希函数设计 2.4 冲突-避免-负载因子调节(重点) 2.5 冲突-解决 2.5.1 闭散列 2.6 冲突-解决- ...
- 【数据结构】哈希表详解以及代码实现
目录 1.来源: 2.哈希函数 1.哈希函数的设计规则 2.哈希函数的设计思路 3.哈希碰撞 4.解决哈希碰撞的方案 5.负载因子 3.基于开散列方案的HashMap实现 1.HashMap类中的属性 ...
- 判断数组中某个元素除自身外是否和其他数据不同_算法工程师要懂的3种算法数据结构:线性表详解...
算法思想有很多,业界公认的常用算法思想有8种,分别是枚举.递推.递归.分治.贪心.试探法.动态迭代和模拟.当然8种只是一个大概的划分,是一个"仁者见仁.智者见智"的问题. 其实这些 ...
- 数据结构个人笔记 第三课 顺序表和单链表
数据结构个人笔记 第三课 顺序表和单链表 顺序表的基本操作 插入元素 删除元素 顺序表查找元素 顺序表更改元素 本节总结代码 单链表 链表的节点 头节点.头指针和首元结点 链表的创建(初始化) 本节总 ...
- 线性表详解(静态链表、单链表、双向链表、循环链表)
目录 申明 1. 线性表的定义 2. 线性表的抽象数据类型 3. 线性表的顺序存储结构 3. 1 顺序存储定义 3. 2 顺序存储方式 3. 3 数据长度与线性表长度区别 3. 4 地址计算方法 4. ...
- 斯坦福NLP名课带学详解 | CS224n 第13讲 - 基于上下文的表征与NLP预训练模型(ELMo, transformer)(NLP通关指南·完结)
作者:韩信子@ShowMeAI,路遥@ShowMeAI,奇异果@ShowMeAI 教程地址:https://www.showmeai.tech/tutorials/36 本文地址:https://ww ...
最新文章
- 雷林鹏分享:jQuery EasyUI 数据网格 - 创建页脚摘要
- linux内核网络协议栈--kernel bridge转发逻辑(十一)
- linux 内核线程与普通进程的区别
- java反射的运用_java反射的使用
- 用C#生成中文汉字验证码的基本原理
- 【渝粤题库】国家开放大学2021春3607矿井瓦斯灾害防治题目
- Xamarin开发笔记—设备类amp;第三方弹窗的使用和注意事项
- 重装系统计算机无法启动,手把手教你电脑无法开机怎么重装系统
- hibernate基本类型映射
- 鸡啄米vc++2010系列7(对话框:创建对话框类和添加控件变量)
- 孟子模型 | 当Bert炼丹不是玄学而是哲学
- springboot 集成redis实现session共享
- (转)wuauclt.exe病毒解决方案
- 用通俗易懂的大白话彻底搞明白mysql的数据类型以及mysql中的int(11),这个11到底是啥?
- 【SCSS】1300- 这些 SCSS 使用技巧真好用~
- knex 单表查询_SQL查询构建器 knex.js
- 第九天 03-破解linux密码
- 一个想法(续三):一份IT技术联盟创业计划书,开启众筹创业征程
- Kerberos协议内容详解
- api返回图片如何在界面中显示
热门文章
- 英文学习20180308
- 点云配准误差衡量标准
- 【PSU】AIX 11g RAC自动打GI PSU5
- 汇编系列02-借助操作系统输出Hello World
- Android traceView使用
- TESTmain.c:(.text+0x15): undefined reference to `TESTscan‘
- Java最前沿技术——ZGC
- 标准化处理鸢尾花数据集
- 由于一些奇妙的原因,获得了一些化学量子结构分析软件。赠予有缘人。
- 探索Java面向对象编程的奇妙世界(一)