文章目录
- 什么是LinkedList
- LinkedList的使用
- LinkedList的构造
- LinkedList的其他常用方法
- LinkedList的遍历
- ArrayList和LinkedList的区别
小贴士:建议学习这章之前先看一下上一章的单向链表哦
什么是LinkedList
LinkedList的底层是双向链表结构(链表后面介绍),由于链表没有将元素存储在连续的空间中,元素存储在单独的节点中,然后通过引用将节点连接起来了,因此在在任意位置插入或者删除元素时,不需要搬移元素,效率比较高。
在集合框架中,LinkedList也实现了List接口,具体如下:
【说明】
- LinkedList实现了List接口
- LinkedList的底层使用了双向链表
- LinkedList没有实现RandomAccess接口,因此LinkedList不支持随机访问
- LinkedList的任意位置插入和删除元素时效率比较高,时间复杂度为O(1)
- LinkedList比较适合任意位置插入的场景
LinkedList的使用
LinkedList的构造
我们在顺序表那一章节中(详见顺序表)详细的探讨过构造函数的问题,当时我们知道构造函数时可以传递一个ArrayList类型的表的参数。不过由于只要是Collection的子类都可以传参,所以传递的参数不仅可以是ArrayList,还可以是任意的其他的类型。比如下面这个案例:
public static void main(String[] args) {
// 构造一个空的LinkedList
List<
Integer> list1 = new LinkedList<
>();
List<
String> list2 = new java.util.ArrayList<
>();
list2.add("JavaSE");
list2.add("JavaWeb");
list2.add("JavaEE");
// 使用ArrayList构造LinkedList
List<
String> list3 = new LinkedList<
>(list2);
}
LinkedList的其他常用方法
这些常用的方法我们很容易就可以模拟实现,并且这些方法在ArrayList那一章中我们就模拟实现过了,所以我们实现一些特殊的方法,具体如下:
还是先建立一个MyList接口,然后再用链表类实现它:
package demo;
public interface MyList {
//头插法
public void addFirst(int data);
//尾插法
public void addLast(int data);
//任意位置插入,第一个数据节点为0号下标
public void addIndex(int index,int data);
//查找是否包含关键字key是否在单链表当中
public boolean contains(int key);
//删除第一次出现关键字为key的节点
public void remove(int key);
//删除所有值为key的节点
public void removeAllKey(int key);
//得到单链表的长度
public int size();
public void clear() ;
public void display() ;
}
双向链表类:
package demo;
// 2、无头双向链表实现
public class MyLinkedList
implements MyList{
static class ListNode
{
public ListNode next;
public ListNode prev;
int val;
public ListNode(int val) {
this.val = val;
}
}
ListNode head;
ListNode last;
//头插法
public void addFirst(int data){
ListNode node = new ListNode(data);
if(head == null){
head = last = node;
return;
}
head.prev = node;
node.next = head;
head = node;
}
//尾插法
public void addLast(int data){
ListNode node = new ListNode(data);
if(last == null){
last = head = node;
return;
}
node.prev = last;
last.next = node;
last = node;
}
//任意位置插入,第一个数据节点为0号下标
public void addIndex(int index,int data){
ListNode cur = head;
ListNode node = new ListNode(data);
if(index == 0){
node.next = head;
head.prev = node;
head = node;
return;
}
if(index == size()){
node.prev = last;
last.next = node;
last = node;
return;
}
while(index != 0){
cur = cur.next;
index--;
}
node.next = cur;
node.prev = cur.prev;
cur.prev.next = node;
cur.prev = node;
}
//查找是否包含关键字key是否在单链表当中
public boolean contains(int key){
ListNode cur = head;
while(cur != null){
if(cur.val == key){
return true;
}
cur = cur.next;
}
return false;
}
//删除第一次出现关键字为key的节点
public void remove(int key){
ListNode cur = head;
while (cur != null) {
if(cur.val == key) {
//开始删除
if(cur == head) {
head = head.next;
if(head != null) {
head.prev = null;
}
}else {
cur.prev.next = cur.next;
if(cur.next == null) {
last = last.prev;
}else {
cur.next.prev = cur.prev;
}
}
return;
}
cur = cur.next;
}
}
//删除所有值为key的节点
public void removeAllKey(int key){
ListNode cur = head;
while (cur != null) {
if(cur.val == key) {
//开始删除
if(cur == head) {
head = head.next;
if(head != null) {
head.prev = null;
}
}else {
cur.prev.next = cur.next;
if(cur.next == null) {
last = last.prev;
}else {
cur.next.prev = cur.prev;
}
}
}
cur = cur.next;
}
}
//得到单链表的长度
public int size(){
ListNode cur = head;
int count = 0;
while(cur != null){
count++;
cur = cur.next;
}
return count;
}
public void display(){
ListNode cur = head;
while(cur != null){
System.out.print(cur.val + " ");
cur = cur.next;
}
System.out.println();
}
public void clear(){
last = null;
head = null;
}
}
还是建议大家可以跟着自己尝试模拟实现一下
LinkedList的遍历
public static void main(String[] args) {
LinkedList<
Integer> list = new LinkedList<
>();
list.addLast(1);
list.addLast(1);
list.addLast(1);
list.addLast(2);
list.add(2,3);
list.add(0,9);
list.addLast(6);
System.out.println("====for循环====");
for (int i = 0; i < list.size(); i++) {
System.out.print(list.get(i) + " ");
}
System.out.println();
System.out.println("====for each循环====");
for(Integer x : list){
System.out.print(x + " ");
}
System.out.println();
System.out.println("====iterator====");
Iterator<
Integer> it = list.iterator();
while(it.hasNext()){
System.out.print(it.next() + " ");
}
System.out.println();
System.out.println("====listIterator反向输出====");
ListIterator<
Integer> it2 = list.listIterator(list.size());
while(it2.hasPrevious()){
System.out.print(it2.previous() + " ");
}
System.out.println();
}
遍历这一部分跟顺序表大差不差,其中迭代器输出的方法还是着重理解一下。