热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

2.数组、链表、跳表的基本实现和特性(7天掌握算法面试必考知识点)

全文内容主要源于极客大学的算法课,仅作为笔记使用。1、数组数组:在内存中,占用连续内存空间的,有序的元素序列。数组元素的类型没有要求,即为泛型。底层原理当申请数组时,内存管理器分配

全文内容主要源于极客大学的算法课,仅作为笔记使用。



1、数组

数组:在内存中,占用连续内存空间的,有序的元素序列。
数组元素的类型没有要求,即为泛型。

底层原理

当申请数组时,内存管理器分配一个连续的内存地址。每一个地址可以直接通过内存管理器进行访问。
如下图所示,即为数组相应的内存地址:

直接访问的话,访问第一个元素和访问任意一个元素,时间复杂度都是一样的,为O(1)。

数组特性

访问速度快

访问数组时,其实是利用指针,即内存地址,直接访问对应内存地址中的数值,所以访问速度非常快。
访问数组的时间复杂度:常数复杂度 O(1)

删除和插入: O(n)

如下图所示:
当向数组中插入元素D时,首先要将E、F、G都向下挪动一个位置,然后将index=3的地址值赋值为D。
同理:


  • 最慢的插入操作:插入位置为第一个元素位置,要挪动n个元素,时间复杂度为O(n)

  • 最快的插入操作:插入位置为最后一个元素位置,不需要挪动元素,时间复杂度为O(1)

  • 平均要挪动一半元素

Array各操作时间复杂度

prepend: O(n),正常情况下是O(n),但是可以进行特殊优化到O(1)。初始化时申请稍大一些的内存空间,然后在数组最开始预留一部分空间,然后prepend操作只需要把头下标千一一个位置即可。
append: O(1)
lookup: O(1)
insert: O(n)
delete: O(n)

2、链表(LinkedList)

概念

链表:元素由Value和next组成,next指向下一个元素,在内存中是非连续空间。链表元素一般由class定义。
单向链表:如果只有一个next指针,是单向链表。
双向链表:如果由两个指针,next指向下一个元素,先前指针prev或previous指向上一个元素。一般头叫做Head,尾叫做Tail。
循环链表:如果next指向Head,叫做循环链表。

LinkedList定义

最简单的链表定义:

class LinkedList {
Node head; // head of list
/* Linked List Node */
class Node {
int data;
Node next;
Node(int d) { data = d; }
}
}

插入和删除

增加节点

330b1a37-fab4-4079-bf6d-4e5213dcb69f.png!large

节点增加步骤:


  • 插入位置前面的node.next指向new node

  • new node的next指向插入位置后面的node 由于只有两步操作,所以时间复杂度为O(1)

删除节点

删除节点为增加节点的逆操作。

删除节点步骤:


  • target_node.prev_node.next = target_node.next_node 只有一步操作,时间复杂度为O(1)。

由此可见,链表的增加和删除,没有引起整个链表的群移操作,也不需要复制元素。所以移动或修改链表的效率非常高,时间复杂度为O(1)。
但是,正因为链表的这种特性,当访问中间节点时,必须从Head Node一步一步往后找,时间复杂度为O(n)

链表各操作时间复杂度

c87905fb-748e-48a0-81eb-8fc2feb3493c.png!large

3、跳表 Skiped List

科学家在数组和链表基础上,优化了新的数据结构,即 跳表。
主要关注:升维思想+空间换时间

跳表的特点

注意:只能用于元素有序的情况。
所以,跳表对标的是平衡树(VAL Tree)和二分查找,是一种插入/删除/查找 都是O(log n)的数据结构。
它最大的优势是原理简单、容易实现、方便扩展、效率更高。因此在一些热门的项目里用于替代平衡树,如Redis、LevelDB等。

如何给有序的链表加速

有序一维数据结构加速理念:经常采用的方式就是升维,也就是说变成二维。
(1)加一级索引

第一级索引指向的是next.next
(2)加二级索引
二级索引next指向的是一级索引链表的next.next

(3)多级索引
以此类推,加多级索引如下图所示:

跳表查询的时间复杂度

n/2、n/4、n/8,第k级索引节点的个数就是n/(2k)
假设索引有h级,最高级的索引有2个结点。n / (2h) = 2,从而求得 h = log2(n) - 1

0b345629-c384-4f27-bcea-6a70b41f5ff4.png!large

假设原始链表要查询1024次的话,那么跳表的时间复杂度是log2(n),即10次就可以找到元素。

现实中的跳表

如下图所示,现实中的跳表,由于多次的增加和删除,导致有些索引并不是完全工整的,最后经过多次改动后,有些地方的索引会多跨几步,有些地方会少跨或只跨两步。
维护成本相对较高,比如增加或删除一个元素的话,索引要更新一遍,此时时间复杂度就变为Logn了。

d61794c6-1cce-428b-8ee5-439a711f9f17.png!large

空间复杂度

跳表的空间复杂度为O(n),但是比原始链表要多很多。

4、更多

LRU缓存算法
跳表在Redis中的使用
跳跃表、为啥 Redis 使用跳表(Skip List)而不是使用 Red-Black?


推荐阅读
  • CSS3选择器的使用方法详解,提高Web开发效率和精准度
    本文详细介绍了CSS3新增的选择器方法,包括属性选择器的使用。通过CSS3选择器,可以提高Web开发的效率和精准度,使得查找元素更加方便和快捷。同时,本文还对属性选择器的各种用法进行了详细解释,并给出了相应的代码示例。通过学习本文,读者可以更好地掌握CSS3选择器的使用方法,提升自己的Web开发能力。 ... [详细]
  • 本文整理了Java中java.lang.NoSuchMethodError.getMessage()方法的一些代码示例,展示了NoSuchMethodErr ... [详细]
  • 生成式对抗网络模型综述摘要生成式对抗网络模型(GAN)是基于深度学习的一种强大的生成模型,可以应用于计算机视觉、自然语言处理、半监督学习等重要领域。生成式对抗网络 ... [详细]
  • android listview OnItemClickListener失效原因
    最近在做listview时发现OnItemClickListener失效的问题,经过查找发现是因为button的原因。不仅listitem中存在button会影响OnItemClickListener事件的失效,还会导致单击后listview每个item的背景改变,使得item中的所有有关焦点的事件都失效。本文给出了一个范例来说明这种情况,并提供了解决方法。 ... [详细]
  • 本文介绍了Redis的基础数据结构string的应用场景,并以面试的形式进行问答讲解,帮助读者更好地理解和应用Redis。同时,描述了一位面试者的心理状态和面试官的行为。 ... [详细]
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • 闭包一直是Java社区中争论不断的话题,很多语言都支持闭包这个语言特性,闭包定义了一个依赖于外部环境的自由变量的函数,这个函数能够访问外部环境的变量。本文以JavaScript的一个闭包为例,介绍了闭包的定义和特性。 ... [详细]
  • 本文讨论了Kotlin中扩展函数的一些惯用用法以及其合理性。作者认为在某些情况下,定义扩展函数没有意义,但官方的编码约定支持这种方式。文章还介绍了在类之外定义扩展函数的具体用法,并讨论了避免使用扩展函数的边缘情况。作者提出了对于扩展函数的合理性的质疑,并给出了自己的反驳。最后,文章强调了在编写Kotlin代码时可以自由地使用扩展函数的重要性。 ... [详细]
  • 本文整理了Java面试中常见的问题及相关概念的解析,包括HashMap中为什么重写equals还要重写hashcode、map的分类和常见情况、final关键字的用法、Synchronized和lock的区别、volatile的介绍、Syncronized锁的作用、构造函数和构造函数重载的概念、方法覆盖和方法重载的区别、反射获取和设置对象私有字段的值的方法、通过反射创建对象的方式以及内部类的详解。 ... [详细]
  • 开源Keras Faster RCNN模型介绍及代码结构解析
    本文介绍了开源Keras Faster RCNN模型的环境需求和代码结构,包括FasterRCNN源码解析、RPN与classifier定义、data_generators.py文件的功能以及损失计算。同时提供了该模型的开源地址和安装所需的库。 ... [详细]
  • 1Lock与ReadWriteLock1.1LockpublicinterfaceLock{voidlock();voidlockInterruptibl ... [详细]
  • GetWindowLong函数
    今天在看一个代码里头写了GetWindowLong(hwnd,0),我当时就有点费解,靠,上网搜索函数原型说明,死活找不到第 ... [详细]
  • Linux重启网络命令实例及关机和重启示例教程
    本文介绍了Linux系统中重启网络命令的实例,以及使用不同方式关机和重启系统的示例教程。包括使用图形界面和控制台访问系统的方法,以及使用shutdown命令进行系统关机和重启的句法和用法。 ... [详细]
  • XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
  • Java学习笔记之面向对象编程(OOP)
    本文介绍了Java学习笔记中的面向对象编程(OOP)内容,包括OOP的三大特性(封装、继承、多态)和五大原则(单一职责原则、开放封闭原则、里式替换原则、依赖倒置原则)。通过学习OOP,可以提高代码复用性、拓展性和安全性。 ... [详细]
author-avatar
mobiledu2502861767
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有