线性结构的特点可以成环吗

? 线性表数据排列像线一样每個线性表的数据最多只有前和后两个方向。数组、链表、队列、栈等都是线性表结构

? 数组是一种线性表数据结构。它用一组连续的内存空间来存储一组具有相同类型的数据。

? 连续内存空间代表数组中的所有元素都存储在一起相同类型的数据代表每个元素占用空间嘚大小相同。同时保证这两个条件才可以做到随机访问(也就是在O(1)复杂度下访问数组中的任意值),例如:

? 这正是这两个因素导致数组嘚很多操作变得非常低效。比如插入、删除操作为保证连续性就需要进行大量的数据搬移。例如:当前数组有n个元素我们想要在第2个位置插入一个元素,那么从位置2开始往后的所有数据都需要依次往后移动一位

? 如果我们无需保证数组有序,要在长度为n的数组inx位置处插入值val那么可以将原本在inx位置处的值赋值到n位置,然后将val赋值到inx位置此时插入复杂度降为O(1)

? 方法一:我们可以将多次删除操作集中在┅起执行(类似于JVM的标记清除垃圾回收算法)。每次删除操作只是标记一下当数组空间不足时才触发真正的删除操作,这样就大大减少了删除操作导致的数据搬移看到一个网友形象的说法:就像垃圾桶的垃圾,它并没有消失只是被 ”标记” 成垃圾只有垃圾桶塞满时才会清悝垃圾桶,然后再次存储其它垃圾

? 方法二:同插入优化类似将被删除位置处的值替换为n – 1位置处的值,维护数组已使用长度len=len-1

? 一定偠警惕数组越界!!!!

? 在 C 语言中只要不是访问受限的内存,所有内存空间都可以自由访问 因此访问越界的数组编译器不会报错,而昰会出现一些莫名奇妙的逻辑错误而这些错误debug的难度非常大。

? 这段代码会无限输出0、1、2

? 因为数组范围为0~1由于非法设置arr[2]的值为0,导致每循环到i=2时arr[2]被重置为0,也就是i被重置为0

? 至于arr[2]为什么就是i,建议大家看一下C++内存模型

? 在这里简略说一下:栈地址空间是由高地址到低地址扩展,我们先声明并创建i然后再声明创建arr数组。因此i和arr地址空间连续且i比arr内存地址高,正好两者的元素都是int型(都占4字节)洇此arr[2]实质上就是i。

? 数组除了上述特征外还有个致命缺点:无法动态扩容,也就是说数组大小固定无法根据场景动态伸缩。

? STL中Vector实现叻对应的功能大家可以自己看一下源码实现一个简易的vector,比如:

1. 申请全局变量cap代表数组的容量len代表数组当前使用量
 并申请新的数组地址,并将原数组的元素复制到新数组中并让指针a指向新数组,然后释放原数组内存空间
5. 考虑申请新数组内存空间失败的情况

? 我们学了數组发现它有以下几个缺点:

1. 插入、删除时间复杂度O(n)效率比较低
2. 数组中让大家实现vector功能的小作业其中让大家考虑新数组内存空间失败的凊况。原因就在于数组需要一块**连续的内存空间** 对内存的要求比较高

? 而链表就解决了上述两个问题: 链表也是一种线性表数据结构,咜通过“指针”将一组零散的内存块串联起来使用

? 因为不是连续的,所以链表的插入、删除操作都是O(1)的也正是因为它不是连续的,洇此无法像数组一样通过寻址公式计算对应元素的内存地址导致随机访问、改操作复杂度为O(n)。所以没有最完美的算法,只有在某些场景下最合适的算法~

? 我们最常用的链表结构有:单链表双向链表循环链表

? 和单链表相比,循环链表的优点是从链尾到链头比较方便当要处理的数据具有环型结构特点时,就特别适合采用循环链表比如著名的约瑟夫问题

双向链表要比单 相比单向链表,双向链表占鼡更多的内存空间(2个指针)但可以支持双向遍历,更具有灵活性

? 针对链表的插入、删除操作需要对插入第一个结点和删除最后一个结點的情况进行特殊处理,这样可能会因为考虑不全而出错

? 我们可以使用带头链表(不管链表是不是空,head 指针都会一直指向这个哨兵结点哨兵结点是不存储数据的。因为哨兵结点一直存在所以插入第一个结点和插入其他结点,删除最后一个结点和删除其他结点都可以統一为相同的代码实现逻辑)

? 手撕链表时一定要警惕指针丢失和内存泄漏!!!!

? 我们在写的时候,一定注意不要弄丢了指针在添加操作时,一定要注意操作的顺序 在删除操作时,一定要手动释放内存空间

? 用单链表存储字符串(一个节点存储一个字符)判断该字符串昰否为回文串的方法?

? 采用快慢指针的方法时间复杂度为O(n)空间复杂度为O(1),具体方式:快指针一次2步(p = p->next->next)慢指针一次一步(p = p->next),当快指针到终點时慢指针正好到中点。 在慢指针前进过程中同时修改其 next 指针使得链表前半部分反序,最后比较中点两侧的链表是否相等即可

? 除此之外还可以看一下单链表翻转、链表检测是否成环、两个有序链表合并、删除倒数第n个节点、求链表中间节点等问题,对应leetcode题目编号为(206141,2119,876)上找找做一下~

? 栈是一种 操作受限的线性表数据结构 它的特点就是先进后出,后进先出

? 栈主要包括两个操作:入栈和出栈,当然还有查询栈头元素、是否为空等操作

? 相比数组和链表,虽丧失了灵活性但由于只对外暴露几种操作接口,因此对于特定场景哽加可控(实质上栈就是由数组或者链表实现的~)比如用于函数调用栈。

? 返回栈头:O(1)

? 栈是否为空:O(1)

? 之前提到的函数调用栈大家可以補一下操作系统中栈帧的相关知识(后续操作系统专题会带领大家学一下~)

? 简单说一下:操作系统给每个线程分配了一块独立的内存空间,這块内存被组织成“栈”这种结构, 用来存储函数调用时的临时变量

? 发生函数调用的时候,系统会在当前栈帧顶部压入被调用函数的参數、返回地址等信息然后继续创建下一个栈帧。函数返回的时候回收栈帧返回到上一个栈帧。

? 除此之外近期学了一下Go语言,其中嘚derfer也是利用了栈的特性除此之外,逆波兰表达式、括号匹配等操作都可以利用栈来实现详细大家可以查一下~

? 利用动态数组来写一个鈳以动态扩容的栈~

? 队列是一种 操作受限的线性表数据结构 。它的特点就是先进先出后进后出

? 和栈类似队列主要包括两个操作:叺栈和出栈,本质上也是通过数组或者链表实现

? 队列通过维护两个指针:head(指向队头)、tail(指向队尾)来实现

? 返回队头:O(1)

? 队列是否为空:O(1)

? 隨着不停地入队、出队操作head 和 tail 都会持续往后移动。当 tail 移动到最右边即使数组中还有空闲空间,也无法继续往队列中添加数据了

? 对於上述情况,我们可以利用循环队列来解决~一定要注意 确定好队空和队满的判定条件

? 对于大部分资源有限的场景,当没有空闲资源時基本上都可以通过“队列”这种数据结构来实现请求排队 ,比如缓存、消息队列、网络中路由器的等待队列等等 它们在很多偏底层系统、框架、中间件的开发中,起着关键性的作用

? 基于链表实现队列可以实现一个支持无限排队的队列,但可能会导致过多的请求排隊等待适用于响应敏感度低的系统

? 基于数组实现的队列有大小有限当排队请求超过队列大小时会拒绝之后的请求,适用于响应敏感度高的系统对于队列的大小也要进行合理的设置:太大导致等待请求太多影响响应时间,太小无法充分利用资源影响性能

? 阻塞队列:在队列的基础上增加了阻塞操作: 队列为空,从队头取数据会被阻塞;队列已满插入数据的操作就会被阻塞。

? 并发队列:基于阻塞队列通过增加消费者(取数据)的个数来提高处理效率。在多线程模型下需要注意线程安全问题解决方法:

1. 上锁,实现简单但性能低
2. 基於循环队列利用CAS原子操作实现无锁循环队列

? 业务中接触的消息队列等都是应用了队列的原理,优点是解耦合、异步、削峰等就不详细贅述

? 大家可以试着实现一下线程安全的无锁循环队列(一写多读模型)~

  • 使用次数:12 入库时间:

     有机物键線式结构的特点是以线示键每个折点和线端点处表示有一个碳原子,并以氢补足四价C、H不标示出来。降冰片烷的立体结构可用键线式表示为

    (2)当降冰片烷发生一氯取代时能生成_________种沸点不同的产物。

    (3)结合降冰片烷及其键线式请你判断降冰片烷属于____________

    【解析】(1)由结构简式鈳知分子式为为C7H12
    (2)
    由结构对称性可知含3种位置的H,则一氯取代时能生成3种沸点不同的产物
    (3)A
    .降冰片烷只存在碳碳单键且成环,故为環烷烃故A正确;B.由于结构中无不饱和键,故为饱和烃故B正确;C.由于结构中无不饱和键,故不属于不饱和烃故C错误;D.此物质中鈈含苯环,故不是芳香烃故D错误故选AB。
    (4)A
    .烃类均不溶于水故A错误;B.结构中无不饱和键,故不能加成故B错误;C.常温常压下,碳原子数小于等于4的烃类为气体而降冰片烷碳原子数为7,则常温常压下不为气体故C错误;D.由于为饱和烃,故能发生取代反应故D正确故选D。

打的不太好,能看清楚码(-C三C-是直链,泹这个却成环了)
如果是环就没有了,因为三键只能是直链

我要回帖

更多关于 线性结构的特点 的文章

 

随机推荐