| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> C++知识库 -> 顺序表的实现和顺序表相关OJ题 -> 正文阅读 |
|
[C++知识库]顺序表的实现和顺序表相关OJ题 |
前言: 从本篇博客开始,我们会逐渐接触一些数据结构,并且我们将会用C语言实现这些数据结构。我希望从这篇博客开始,读者能够学会画好图在写代码,代码运行出错进行自主调试来分析错误,如果你能够养成这两个良好习惯,那么不仅对你后续的数据结构学习有很大的帮助,而且还会对未来从事本行业有很大的帮助! 目录 1.什么是顺序表 2.顺序表的增删改查 3.顺序表的优缺点 4.顺序表相关的OJ题 一.什么是顺序表:
顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组存储。在数组上完成数据的增删改查。
顺序表又可以分成两种:
?静态顺序表:本质就是数组,
这种结构不够灵活,空间太小不够使用,空间大大有可能造成 空间的浪费!所以一般来讲静态的顺序表有很多的缺点,所以在实际的开发中并不太经常使用。
所以说在实际的开发过程中使用的更多的是动态的顺序表,使用动态开辟的数组存储。
2.顺序表的增删改查 了解了顺序表的结构,接下来我们进行顺序表的增删改查,我们实现的是动态的顺序表,使用的计算机语言是C语言。和标准的工程一样,我们创建三个文件:
下面是SeqList.h的内容:
我们接下来按顺序逐一实现每个函数: 首先SeqListInit的作用是对顺序表进行初始化,显然开始的顺序表里什么都没有,所以我们可以这样初始化:
这里我们传递的是结构体指针而非结构体。原因有二:1.我们要修改对应的结构体就必须要传递地址才能对它起到真正的修改作用!2.结构体指针传参的传递效率高(次要原因)而我们因为要涉及对结构体指针的解引用,所以我们要对ps指针断言,防止对空指针的解引用! 2.因为动态顺序表使用的是动态内存管理的相关知识,所以在不需要顺序表了以后要释放内存,防止造成内存泄露,所以我们写了SeqListDestroy函数来释放顺序表:
3.打印顺序表的接口很简单,直接上代码不做过多解释:
4.顺序表尾插数据 假设我们有这样的一个顺序表:[1,2,3,4],接下来我们要在尾部插入数据5,我们应该怎么做呢?首先,我们知道顺序表除了动态分配的指针外,还有记录有效数据数量大小的size以及顺序表容量capacity,不难可以观察出size总是指向当前顺序表最后一个元素的下一个位置,因此我们直接就可以在下标为size的地方放元素。但是我们当size==capacity的情况要进行扩容,所以在每一次插入元素之前都要进行检查,所以我们可以把检查容量也封装成一个接口:
这就是顺序表尾插元素的实现,相对来说比较简单,尾插数据的时间复杂度是O(1),所以对于顺序表尾插数据是非常快速的。 5.顺序表的头插数据: 相比较于尾插数据,头插数据就会复杂一点,那么头插要在顺序表的头部插入数据,而顺序表为了保持数据连续存储的特点,因此要对数据进行挪动,我们先来画图分析怎么挪动
?那么画出了逻辑图,接下来写代码就比较容易了:
好了,到这里我们就写好了头插和尾插,这里在提一提我的这个函数的命名。这里的头插和尾插你也可以叫做insertfront或者是insertback,但是千万不要用拼音,面试官看到你会对你的印象分大打折扣,也会被同事嘲笑!!至于这里我取名pushback和pushfront的原因是因为C++的STL就是这样的命名头插和尾插的。 讲了头插和尾插,对应的我们就要介绍头删和尾删,先来介绍尾删: 尾删就是从尾部删除数据,但是需要注意的是,这个数据并不是真正地被删除!类似于函数栈帧的释放,我们所谓的删除数据的本质就是这个数据可以被覆盖!这点要特别注意: 尾删的代码很简单,只要size--即可,但是要注意当size成0的时候就不要在执行自减操作了
头删:和头插一样,进行头删操作的时候同样需要挪动数据,所有的数据都要向前挪动一位,我们同样通过画图分析我们应该怎么挪动数据
?画完逻辑图以后,我们就可以上手写头删的代码
在有些的应用场景下,我们要在顺序表的任意位置插入和删除元素,所以我们还需要提供这样的一类的接口,我们把插入的方法命名为Insert和Erase(c++标准库的命名规范) Insert方法可以指定插入的下标pos,我们可以讲向指定的位置插入元素,具体的实现过程如下图:
?那么结合图片,我们就可以写出如下的代码:
我们接下来实现在 任意位置删除的方法Erase,类比于前面的尾删和头删,顺序表的删除的本质是将原来位置的数据覆盖,和Insert方法类似,Erase方法也需要挪动元素,我们可以画图分析: ?有了图的分析,接下来我们就可以实现代码了
现在只剩下了find没有完成了,这个函数就是遍历顺序表,代码如下:
那么到这里,一份简易的动态顺序表就写好了。但是,其实我们的头插尾插以及头删尾删是可以复用Insert和Erase的,即:
3.顺序表的优缺点 从结构可以看出,顺序表的一个最大的优点就是我们访问顺序表的元素的时间复杂度是O(1),但它的缺点也很明显,就是除了在尾部插入和删除元素是o(1)的时间复杂度,其他位置的插入和删除元素的时间复杂度是O(n)!另外顺序表扩容的时候也不可避免地会带来性能的消耗和空间的浪费 4.顺序表的OJ题 前面,我们 了解了顺序表的增删查改,大多数真实的面试的场景下并不会直接让你上手写增删查改功能,而是通过一些OJ题来考察增删查改,下面我们就来看几道顺序表相关的OJ题: 1.删除有序数组中的重复项 https://leetcode-cn.com/problems/remove-duplicates-from-sorted-array/ ? ? ?那么如果考虑使用额外空间的话,那么想法就比较简单:
解决方案:双指针法,以案例2画图分析为例:
?画好图,接下来写代码就能一气呵成,写出的代码一跑就能过:
? ?2.原地移除值为val的元素:https://leetcode-cn.com/problems/remove-element/ ?
? ?3.合并两个有序数组:https://leetcode-cn.com/problems/merge-sorted-array/ ? ?
?方法2的代码如下:
这里我们只需要处理nums2还没有结束的情况,因为我们是合并到nums1所以我们并不需要处理nums1为空的情况,所以我们只要处理nums2不为空的情况就可以了。 基于顺序表有这在插入和删除方面的性能的消耗,所以说我们后续会使用一个方便插入和删除的数据结构----->链表,敬请期待 |
|
C++知识库 最新文章 |
【C++】友元、嵌套类、异常、RTTI、类型转换 |
通讯录的思路与实现(C语言) |
C++PrimerPlus 第七章 函数-C++的编程模块( |
Problem C: 算法9-9~9-12:平衡二叉树的基本 |
MSVC C++ UTF-8编程 |
C++进阶 多态原理 |
简单string类c++实现 |
我的年度总结 |
【C语言】以深厚地基筑伟岸高楼-基础篇(六 |
c语言常见错误合集 |
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/24 3:14:22- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |