LinkedList的实现源码分析
LinkedList
以双向链表实现。链表无容量限制,但双向链表本身使用了更多空间,也需要额外的链表指针操作。
按下标访问元素--get(i)/set(i,e) 要悲剧的遍历链表将指针移动到位(如果i>数组大小的一半,会从末尾移起)。
插入、删除元素时修改前后节点的指针即可,但还是要遍历部分链表的指针才能移动到下标所指的位置,只有在链表两头的操作--add(), addFirst(),removeLast()或用iterator()上的remove()能省掉指针的移动。
在介绍LinkedList之前我们来回顾下链表的类型,链表主要包含单向链表,单向循环链表,双向链表,双向循环链表。具体的图我就不在这边画出了,不清楚的可以自行百度。LinkedList是属于双向链表,下图是包含头结点和尾节点的双向链表。

本篇内容主要讲解下LinkedList这个双向链表在java的源码的实现,主要包含有add,remove,get,set等方法的介绍。
首先我们来看下add方法的实现,下图演示了下节点插入的过程,包含了4个步骤。

我们来看下java的源码,从代码可知insert节点是查在链表尾部的
```java
public boolean add(E e) {
linkLast(e);
return true;
}
void linkLast(E e) {
final Node l = last;
final Node newNode = new Node<>(l, e, null);
last = newNode;
if (l == null)
first = newNode;
else
l.next = newNode;
size++;
modCount++;
}
private static class Node {
E item;
Node next;
Node prev;
Node(Node<E> prev, E element, Node<E> next) {
this.item = element;
this.next = next;
this.prev = prev;
}
}
<p>因为add(E e)是插在末尾,所以实际上我们只需要做两部操作,吧NewNode的prew指向最后一个节点,把最后一个几点的next指向newNode
```java
void linkBefore(E e, Node<E> succ) {
// assert succ != null;
final Node<E> pred = succ.prev;
final Node<E> newNode = new Node<>(pred, e, succ);
succ.prev = newNode;
if (pred == null)
first = newNode;
else
pred.next = newNode;
size++;
modCount++;
}
上面的insertBefore就是执行4个操作了:
1.把新节点newNode的prev指向succ.prev
2.把succ.prev的next执行newNode
3.newNode的next指向succ
4.succ的prev指向newNode
第3、4步已经在Node的构造函数做了,java是执行顺序是3、4、1、2
下面来看下删除的实现

下面看下java的实现,具体下面代码逻辑很简单,就是获取要删除的节点x的prev节点为prev,x的下节点为next。
然后按如图执行prev.next=next;next.prev=prev;
E unlink(Node<E> x) {
// assert x != null;
final E element = x.item;
final Node<E> next = x.next;
final Node<E> prev = x.prev;
if (prev == null) {
first = next;
} else {
prev.next = next;
x.prev = null;
}
if (next == null) {
last = prev;
} else {
next.prev = prev;
x.next = null;
}
x.item = null;
size--;
modCount++;
return element;
}
set和get函数
```java
public E set(int index, E element) {
checkElementIndex(index);
Node x = node(index);
E oldVal = x.item;
x.item = element;
return oldVal;
}
public E get(int index) {
checkElementIndex(index);
return node(index).item;
}
这个两个函数都用到了node函数,又都要用到查询,所以首先要判断index是否大于index/2,大于的话就从尾节点开始查,反正从前节点查。
```java
Node<E> node(int index) {
// assert isElementIndex(index);
if (index < (size >> 1)) {
Node<E> x = first;
for (int i = 0; i < index; i++)
x = x.next;
return x;
} else {
Node<E> x = last;
for (int i = size - 1; i > index; i--)
x = x.prev;
return x;
}
}
这样的设计可以提高查询效率,时间复杂度为O(n/2)。
参考
数据结构与算法分析_java语言描述(第2版).韦斯
LinkedList的实现源码分析的更多相关文章
- ArrayList、LinkedList和Vector源码分析
ArrayList.LinkedList和Vector源码分析 ArrayList ArrayList是一个底层使用数组来存储对象,但不是线程安全的集合类 ArrayList的类结构关系 public ...
- LinkedList详解-源码分析
LinkedList详解-源码分析 LinkedList是List接口的第二个具体的实现类,第一个是ArrayList,前面一篇文章已经总结过了,下面我们来结合源码,学习LinkedList. 基于双 ...
- ArrayList和LinkedList和Vector源码分析
ArrayList源码: private static final int DEFAULT_CAPACITY = 10;//默认长度 /** * Shared empty array instance ...
- LinkedList 源码分析(JDK 1.8)
1.概述 LinkedList 是 Java 集合框架中一个重要的实现,其底层采用的双向链表结构.和 ArrayList 一样,LinkedList 也支持空值和重复值.由于 LinkedList 基 ...
- java集合源码分析(六):HashMap
概述 HashMap 是 Map 接口下一个线程不安全的,基于哈希表的实现类.由于他解决哈希冲突的方式是分离链表法,也就是拉链法,因此他的数据结构是数组+链表,在 JDK8 以后,当哈希冲突严重时,H ...
- 【集合框架】JDK1.8源码分析之LinkedList(七)
一.前言 在分析了ArrayList了之后,紧接着必须要分析它的同胞兄弟:LinkedList,LinkedList与ArrayList在底层的实现上有所不同,其实,只要我们有数据结构的基础,在分析源 ...
- Java源码分析之LinkedList
LinkedList与ArrayList正好相对,同样是List的实现类,都有增删改查等方法,但是实现方法跟后者有很大的区别. 先归纳一下LinkedList包含的API 1.构造函数: ①Linke ...
- LinkedList其实就那么一回事儿之源码分析
上篇文章<ArrayList其实就那么一回儿事儿之源码分析>,给大家谈了ArrayList, 那么本次,就给大家一起看看同为List 家族的LinkedList. 下面就直接看源码吧: p ...
- Java集合源码分析(二)Linkedlist
前言 前面一篇我们分析了ArrayList的源码,这一篇分享的是LinkedList.我们都知道它的底层是由链表实现的,所以我们要明白什么是链表? 一.LinkedList简介 1.1.LinkedL ...
随机推荐
- IOS开发 图形绘制,绘制线条,矩形,和垂直和居中绘制文字
概述 吐槽下IOS下 的图形绘图,代码冗长,不得不自己重新封装方法.整理形成本文. 绘制线 // 绘制直线 + (void)toDrawLineFromX:(CGFloat)x1 Y:(CGFloat ...
- php 碎片笔记
1.修改 php.ini 加载路径 添加环境变量 ,新建系统变量 PHPRC ,配置如下: 检验: 通过phpinfo(),查看系统配置 Loaded Configuration File ,识别系统 ...
- 2 个UserControl 的传值问题
问题描述:有2个UserControl:UserControl1 里有一个Button,UserControl2 里面有一个TextBox,这2个控件都加载到了主窗体Form1 上.要求的是,点击 U ...
- react-native SyntaxError xxxxx/xx.js:Unexpected token (23:24)
在运行react-native项目时提示 SyntaxError xxxxx/xx.js:Unexpected token (23:24) 我这边的问题原因:jsx语法错误,解决办法就是认真排查代码然 ...
- python 大数据分析
#coding:utf-8 ''' @author solq by 2016-01-06 main(目录,正则过滤文件名) 执行完最后打印结果 ''' import json import fnmat ...
- [转]GeoHash核心原理解析
原文出处: zhanlijun 引子 机机是个好动又好学的孩子,平日里就喜欢拿着手机地图点点按按来查询一些好玩的东西.某一天机机到北海公园游玩,肚肚饿了,于是乎打开手机地图,搜索北海公园附近的餐 ...
- winform用户控件
用途用户控件包含Time控件和一个lable控件,一个ToolStrip控件,每隔一秒显示一次时间 1. 生成用户控件 新建一个项目类型为用户控件 注意定义类名,此类名为以后工具箱中显 ...
- How to change statusbar text color to dark on android 4.4
Because I haven't enough votes, so post picture at here, thank you. Almost 2 weeks ago, I was search ...
- Webkit CSS properties
Webkit CSS properties -webkit-animation -webkit-animation-delay -webkit-animation-direction -webkit- ...
- 【leetcode】3 SUM
3 SUM 原题: Given an array S of n integers, are there elements a, b, c in S such that a + b + c = 0? F ...