算法第一周_数组,链表,跳表,栈,队列,优先队列,双端队列基础知识总结

一,数组,链表,跳表的基本实现和特性

1.1数组(array或者叫array list)的常见写法

java,c++: int a[100];  #100表示数组的大小
python: list = []
javescript: let x = [1,2,3]

1.2数组创建和访问,增加和删除

如下图,创建数组时是在内存空间中开辟一段连续的空间,当访问的时候时通过内存管理器来进行访问,访问每个元素的时间复杂度都为O(1),可以随机的访问任何一个元素,所以访问时间时非常快的。
在这里插入图片描述
数组的增加和删除涉及到很多的移动,在java中使用arraycopy来实现的,并且如果当前数组长度不够,还会copy到一个新数组中,这样时间复杂度和空间复杂度都是比较高的,因此在修改,增加,增加操作比较频繁的场景下数组时不合适的
时间复杂度:
在这里插入图片描述

1.3 链表(linkd list)

链表在创建好之后时有value和next组成,next指向下一个元素,串在一起就形成了一个类似于数组的几个结构。
它的每一个元素一般用class来定义,这个class一般叫做node,这个node有两个成员变量,一个是value(也可以是一个类,类型很丰富),一个是next指针。
在这里插入图片描述
链表的类型:
单向链表,双向链表,循环链表
链表的实现:
在这里插入图片描述
增加,删除,访问的时间复杂度:
增加删除只是移动元素的指针,不涉及批量元素的平移删除,所以时间复杂度为O(1),访问的话只能从开头进行访问,就会比较复杂。
时间复杂度:
在这里插入图片描述

1.4 跳表(Skip list)

对链表进行优化形成了跳表,虽然是基于链表的,但是出现的时间比二叉树等高级数据结构要出现的晚。
比如我们在数据库中使用链表存储的时候是按照有序来存储的,如下:

在这里插入图片描述
现在如果我们查找5或者9,在数组中可以使用二分查找很快就找到。但是如果是一个链表呢,使用什么来进行加速呢?
跳表的特点:
在这里插入图片描述
如何给有序的链表加速:
在这里插入图片描述
一维的数据结构要加速,一般要升维,变成二维,所以我们在原始链表上添加一级索引增加一维:
在这里插入图片描述
添加二级索引,可以再增加一维:
在这里插入图片描述
下面是一个五级索引的查找过程:
在这里插入图片描述
最终得到跳表的时间复杂度为:
在这里插入图片描述
现实中的跳表:
因为会增加删除元素,造成他的结构并不是工整的,有些地方跨的多,有些会跨的少。
在这里插入图片描述
跳表的劣势:
增加删除元素时,需要对这个元素每一层的索引都进行更新。
这种情况下增加删除的时间复杂度就为logn了
跳表的空间复杂度:
在这里插入图片描述

现在的各种语言中都已经封装好了Linkd list,我们直接使用就好了。
总结:
1.数组的时间复杂度(重要)
2.工程应用(redis,LUR)
3.跳表的思想:升维-用空间换时间

二,栈(stack)与队列(queue)

关键点:
stack先进后出,添加删除的时间复杂度都为O(1),因为是无序的,所以查询时间复杂度为O(n),需要将数据都遍历一遍。
queue先进先出,添加删除的时间复杂度都为O(1),因为是无序的,所以查询时间复杂度为O(n),需要将数据都遍历一遍。
模型图如下:
在这里插入图片描述
在这里插入图片描述
实战中纯的stack和queue使用是很少的。

三,双端队列(Deque)

相对于stack和queue实战中使用较多的是Deque,是stack两者的结合体,两端都可以进,也都可以出。

模型图如下:
在这里插入图片描述
时间复杂度:
添加和删除的时间复杂度是O(1),查询的时间复杂度是O(n)

四,优先队列(priority queue)

关键点:

  • 插入时间复杂度O(1)
  • 取出时间复杂度O(logn),按元素优先级取出,相对于普通的队列取出的时间复杂度是增加了,不再是先进先出,但是应用场景比较广泛,可以应用在VIP优先级高的场景。
  • 底层实现的数据结构较为复杂和多样性,可以是heap,bst等等,优先队列定义的也是一个接口,或者说是一种抽象的数据结构。
    小结:在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/a18829292719/article/details/110499186
今日推荐