20220825学习内容 LinkedList

本文详细介绍了Java中的LinkedList数据结构,它是一种双向链表,适用于增删操作,但查询速度较慢。LinkedList包含头节点和尾节点,通过内部类Node存储数据并维护前后节点的链接。文章讨论了LinkedList的构造器、add方法(包括在末尾添加元素和在指定位置插入元素)、删除和查找操作,以及其线程不安全的特性。
摘要由CSDN通过智能技术生成

LinkedList:双向链表实现,增删快,查询慢 (线程不安全)

属性:
transient int size = 0; 存储的元素个数
transient Node<E> first; 头节点
transient Node<E> last; 尾节点

节点的定义
private static class Node<E> {  静态内部类
E item;  节点上存储的具体数据
Node<E> next;  指向下一个节点
Node<E> prev;  指向上一个节点

//创建节点对象的参数
* prev前一个节点的引用  element具体存储的数据   next下一个节点引用
Node(Node<E> prev, E element, Node<E> next) {
this.item = element;
this.next = next;
this.prev = prev;
}
}

构造器方法:

public LinkedList() {
}

没有指定容积的构造器,理论上来说,链表实际上没有长度限制,但是int size属性要求元素个数必须在[0,Integer.max-value]范围内


add方法的定义:在双向链表的末尾新增元素
public boolean add(E e) {
linkLast(e);
return true;
}

void linkLast(E e) {
final Node<E> l = last;  缓存尾节点
final Node<E> newNode = new Node<>(l, e, null);  创建新的节点,新节点的下一个节点为null
last = newNode;  将尾指针执行新创建的节点
if (l == null)   如果原来的尾节点为null,则新增的节点应该是链表的第一个节点
first = newNode;  将头指针指向新创建的节点
else  
l.next = newNode;  如果原来的尾节点不为null,则表示已经有元素了,将原来的尾节点指向新创建的节点,这样就将新节点加入到链表中
size++; 链表中元素个数加1
modCount++;  修改次数加1
}

add(int,Object) 在指定位置新增元素,原来位置上的元素后移

public void add(int index, E element) {
checkPositionIndex(index); 检查index的合法性,要求index应该是在[0,size]的范围内
index >= 0 && index <= size;如果不合法则抛出异常IndexOutOfBoundsException
if (index == size)  如果索引值index等于size,则在链表默认添加元素
linkLast(element);
else  在指定下标位置之前添加元素
linkBefore(element, node(index));
}

获取指定位置上的节点对象

Node<E> node(int index) {
if (index < (size >> 1)) { 如果序号值小于size/2则从头指针开始遍历链表,查找指定索引值的元素Node
Node<E> x = first;
for (int i = 0; i < index; i++)
x = x.next;  从前向后遍历
return x;
} else { 如果序号值大于等于size/2则从尾指针开始遍历链表,查找指定索引值的元素Node
Node<E> x = last;
for (int i = size - 1; i > index; i--)
x = x.prev;  从后向前遍历
return x;
}
}

在指定节点对象之前添加e数据
 

void linkBefore(E e, Node<E> succ) {
final Node<E> pred = succ.prev;  获取指定位置的前一个节点
final Node<E> newNode = new Node<>(pred, e, succ); 
 创建节点对象,参数1是原始节点的前一个节点,参数2是具体存储的数据,
参数3是原始位置上的节点
succ.prev = newNode;  设置原始位置上的node对象的前一个节点为新创建的节点【双向链表】
if (pred == null)  如果指定位置的节点的前一个节点为null,则插入的新节点应该就是头节点
first = newNode;  使头指针指向新创建的节点
else   设置前一个节点的下一个节点指针指向新创建的节点
pred.next = newNode;
size++;  元素个数加1
modCount++;  修改次数加1
}

删除和参数相等的第一个元素,删除成功返回true,否则返回false
 

public boolean remove(Object o) {
if (o == null) {  删除值为null的元素,使用==判断
for (Node<E> x = first; x != null; x = x.next) {从头指针开始执行遍历,
查找第一个值为null的节点
if (x.item == null) {  //判断当前节点的值是否为null
unlink(x);  删除指定的Node节点,并且返回Node中存储的数据
return true;  
}
}
} else {  删除值非null的元素,判断使用equals方法
for (Node<E> x = first; x != null; x = x.next) {
if (o.equals(x.item)) { 判断当前需要删除的数据和节点中的数据是否相等
unlink(x);  删除指定的Node节点,并且返回Node中存储的数据
return true;
}
}
}
return false;
}

删除指定的Node节点,并且返回Node中存储的数据
 

E unlink(Node<E> x) { 
final E element = x.item;  获取节点中的数据
final Node<E> next = x.next;  获取节点的下一个节点对象的引用
final Node<E> prev = x.prev;  获取上一个节点
if (prev == null) { 如果当前节点的前一个节点为null,则表示当前节点为头节点
first = next;  使头指针指向当前节点的下一个节点
} else { 如果不是头节点
prev.next = next;   上一个节点的下一个节点为当前节点的下一个节点,
将当前节点从链表中剔除出来
x.prev = null;  当前节点的上一个节点赋null值
}
if (next == null) {如果当前节点的下一个节点为null,则表示当前节点为尾节点
last = prev; 使尾指针指向当前节点的上一个节点
} else {  如果不是尾节点
next.prev = prev; 下一个节点的上一个节点引用值为当前节点的上一个节点,
将当前节点从链表中剔除出来
x.next = null; 当前节点的下一个节点赋null值
}
x.item = null; 将当前节点的数据赋null值
size--; 链表中的元素个数-1
modCount++; 修改次数+1
return element; 返回当前节点原来的数据
}

按照指定的索引序号删除对应的元素,同时返回删除元素的具体数据值
 

public E remove(int index) {
checkElementIndex(index);  
检查序号值是否合法,不合法抛出异常IndexOutOfBoundsException  index >= 0 && index < size
return unlink(node(index));  
首先查找指定索引序号对应的节点对象,然后删除对应的节点,返回原来节点上存储的具体数据
}

修改操作

public E set(int index, E element) {
checkElementIndex(index);
Node<E> x = node(index);
E oldVal = x.item;  //获取原始节点存储的数据
x.item = element;  //修改节点上的数据为新值
return oldVal;  //返回原始存储的数据
}

查找操作,如果找到则返回索引序号,如果没有找到则返回-1
 

public int indexOf(Object o) {
int index = 0;
if (o == null) {
for (Node<E> x = first; x != null; x = x.next) {
if (x.item == null)
return index;
index++;
}
} else {
for (Node<E> x = first; x != null; x = x.next) {
if (o.equals(x.item))
return index;
index++;
}
}
return -1;
}

import java.util.LinkedList;

public class TestLinkedList {
LinkedList ll;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值