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

数组(ArrayList)

基础写法:int a[100];

优点
每当我们申请数组的时候,计算机实际上是在内存中给我们开辟了一段连续的地址,每一个地址通过内存管理器进行访问,如图:
数组、链表、跳表的基本实现和特性_第1张图片
直接访问时间复杂度都为O(1),它可以随机访问任何一个元素,所以它的访问时间非常快。

缺点
在增加和删除数组元素的时候会进行一些相应的操作。
插入操作:
在插入C之前,我们要将DE往下挪一个位置,把3号位置让出来,然后将C放进去。导致插入的操作不是常数级的,而是O(n)的复杂度。
数组、链表、跳表的基本实现和特性_第2张图片
删除同理。
在ArrayList中,如果超出数组长度,就会将数组长度扩增加一倍

链表(Linked List)

在一些添加和删除操作比较频繁的情况下,我们经常会使用链表。它所做的一件事情就是元素定义好之后,有所谓的value和next,next指向下一个元素,那么串在一起就变成了一个类似与数组的这么的一个结构。每一个元素用class定义,这个class一般叫做node。里面有两个成员变量,一个叫value(也可以是个类),一个next指针,指向下一个元素。如果只有一个next指针,我们叫单链表;有的时候,我们需要往前指一个就叫它的prev或者previous,这个链表我们叫做双链表。即能往后面走,也能往前面走,同理,它的头指针叫head,尾指针叫tail来表示。最后一个元素,它的next指针指向空。另外一种情况是,如果tail指针的next也可以指回到head来,我们叫其为循环链表。

标准实现:

class LinkedList{
    Node head;
    class Node{
        int data;
        Node next;
        Node(int a){
            data=a;
        }
    }
}

添加元素
首先,为这个新元素创造一个节点,我们叫做new node,在链表下发放好,假设,我们要插入第二个位置,我们要将前一个节点的next指向新节点,新元素的next指向原来的下一个节点。
数组、链表、跳表的基本实现和特性_第3张图片删除就是添加的逆操作。
在链表中,不管是增加还是删除节点,它都没有引起链表的群移操作,也不需要复制元素,挪动元素到新的位置,所以它的移动和修改的效率非常高,为O(1)。

缺点
但是,因为这种结构,导致了我们访问这个链表中的任何一个位置,需要的复杂度为O(n)。

链表的时间复杂表

prepend(增加) O(1)
append O(1)
lookup(查看) O(n)
insert O(1)
delete O(1)

跳表(Skip List)

跳表是为了优化或者是弥补链表的缺陷而设计的。

中心思想
升维,或者叫做空间换时间。
简单优化:添加头中尾指针。

添加一级索引
数组、链表、跳表的基本实现和特性_第4张图片
一级索引指针指向头指针这是第一个,它的下一个位置指向next+1的位置。索引基于链表,链表是走向next,索引的话每次向next+1也就是两倍的next。next的每次速度为1,一级索引每次速度为2.

当然,我们还可以再增加一级索引,让速度变得更快。
数组、链表、跳表的基本实现和特性_第5张图片

以此类推,我们可以增加多级索引。

跳表查询的时间复杂度
索引的高度:logn,每层索引遍历的节点个数:3
在跳表中查询任意元素的时间复杂度就是O(logn)

跳表的时间复杂度为O(n)。

你可能感兴趣的:(数据结构与算法)