Java中的LinkedList

文章目录

  • 前言
  • 一、LinkedList的使用
    • 1.1 什么是LinkedList
    • 1.2 LinkedList的使用
      • 1.2.1 LinkedList的构造
      • 1.2.2 LinkedList的其他常用方法介绍
      • 1.2.3 LinkedList的遍历
  • 二、LinkedList的模拟实现
  • 三、ArrayList和LinkedList的区别
  • 总结


前言

上一节中我们讲解了Java中的链表,以及几个链表常见的面试题,浅提了一下LinkedList。接下来我们就来详细讲解Java中的LinkedList。


一、LinkedList的使用

1.1 什么是LinkedList

LinkedList官方文档
LinkedList的底层是双向链表结构,由于链表没有将元素存储在连续的空间中,而是存储在单独的节点中,然后通过引用将节点连接起来了,因此在任意位置插入或者删除元素时,不需要搬移元素,效率比较高。

Java中的LinkedList_第1张图片

在集合框架中,LinkedList也实现了List接口。

注意:

  1. LinkedList实现了List接口
  2. LinkedList的底层使用了双向链表
  3. LinkedList没有实现RandomAccess接口,因此LinkedList不支持随机访问
  4. LinkedList的任意位置插入和删除元素时效率比较高,时间复杂度为O(1)
  5. LinkedList比较适合任意位置插入的场景

1.2 LinkedList的使用

1.2.1 LinkedList的构造

1.无参构造		LinkedList()
2.使用其他集合容器中的元素构造List		public LinkedList(Collection c)

代码如下:

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);
}

1.2.2 LinkedList的其他常用方法介绍

boolean add(E e)	//尾插e

void add(int index,E element)	//将e插入到index位置

boolean addAll(Collection c)	//尾插c中的元素

E remove(int index)	//删除Index位置的元素

boolean remove(Object o)	//删除遇到的第一个o

E get(int index)	//获取下标index位置的元素

E set(int index,E element)	//将下标为index位置的元素设置为element

void clear()	//清空

boolean contains(Object o)	//判断o是否在线性表中

int indexOf(Object o)	//返回第一个o所在下标

int lastIndexOf(Object o)	//返回最后一个o所在下标

ListsubList(int fromIndex,int toIndex)	//截取部分list

代码如下:

public static void main(String[] args) {
	LinkedList<Integer> list = new LinkedList<>();
	list.add(1); // add(elem): 表示尾插
	list.add(2);
	list.add(3);
	list.add(4);
	list.add(5);
	list.add(6);
	list.add(7);
	System.out.println(list.size());
	System.out.println(list);
	// 在起始位置插入0
	list.add(0, 0); // add(index, elem): 在index位置插入元素elem
	System.out.println(list);
	list.remove(); // remove(): 删除第一个元素,内部调用的是removeFirst()
	list.removeFirst(); // removeFirst(): 删除第一个元素
	list.removeLast(); // removeLast(): 删除最后元素
	list.remove(1); // remove(index): 删除index位置的元素
	System.out.println(list);
	// contains(elem): 检测elem元素是否存在,如果存在返回true,否则返回false
	if(!list.contains(1)){
		list.add(0, 1);
	}
	list.add(1);
	System.out.println(list);
	System.out.println(list.indexOf(1)); // indexOf(elem): 从前往后找到第一个elem的位置
	System.out.println(list.lastIndexOf(1)); // lastIndexOf(elem): 从后往前找第一个1的位置
	int elem = list.get(0); // get(index): 获取指定位置元素
	list.set(0, 100); // set(index, elem): 将index位置的元素设置为elem
	System.out.println(list);
	// subList(from, to): 用list中[from, to)之间的元素构造一个新的LinkedList返回
	List<Integer> copy = list.subList(0, 3); 
	System.out.println(list);
	System.out.println(copy);
	list.clear(); // 将list中元素清空
	System.out.println(list.size());
}

1.2.3 LinkedList的遍历

public static void main(String[] args) {
	LinkedList<Integer> list = new LinkedList<>();
	list.add(1); // add(elem): 表示尾插
	list.add(2);
	list.add(3);
	list.add(4);
	list.add(5);
	list.add(6);
	list.add(7);
	System.out.println(list.size());
	// foreach遍历
	for (int e:list) {
		System.out.print(e + " ");
	}
	System.out.println();
	// 使用迭代器遍历---正向遍历
	ListIterator<Integer> it = list.listIterator();
	while(it.hasNext()){
		System.out.print(it.next()+ " ");
	}
	System.out.println();
	// 使用反向迭代器---反向遍历
	ListIterator<Integer> rit = list.listIterator(list.size());
	while (rit.hasPrevious()){
		System.out.print(rit.previous() +" ");
	}
	System.out.println();
}

二、LinkedList的模拟实现

代码如下:

public class MyLinkedList {
    static class LinkedList {
        public int val;
        public LinkedList prev;
        public LinkedList next;
        public LinkedList(int val) {
            this.val = val;
        }

    }
        public LinkedList head;
        public LinkedList last;
    // 2、无头双向链表实现
        //头插法
        public void addFirst(int data){
            LinkedList node = new LinkedList(data);
            if(head==null) {
                head = node;
                last = node;
            } else {
                head.prev = node;
                node.next = head;
                head = node;
            }
        }
        //尾插法
        public void addLast(int data){
            LinkedList node = new LinkedList(data);
            if(head==null) {
                head=node;
                last=node;
            } else {
                last.next=node;
                node.prev=last;
                last = node;
            }

        }
        //任意位置插入,第一个数据节点为0号下标
        public void addIndex(int index,int data){
            if(index<0 || index>size()) {
                System.out.println("位置不合法");
            }
            if(index==0) {
                addLast(data);
                return;
            }
            if(index==size()) {
                addLast(data);
                return;
            }

            LinkedList node = new LinkedList(data);
            LinkedList cur = findIndex(index);
            node.next = cur;
            cur.prev.next = node;
            node.prev = cur.prev;
            cur.prev=node;
        }

        public LinkedList findIndex(int index) {
            LinkedList cur = head;
            while (index!=0) {
                cur = cur.next;
                index--;
            }
            return cur;
        }
        //查找是否包含关键字key是否在链表当中
        public boolean contains(int key){
            LinkedList cur = head;
            while (cur!=null) {
                if(cur.val==key) {
                    return true;
                }
                cur = cur.next;
            }
            return false;
        }
        //删除第一次出现关键字为key的节点
        public void remove(int key){
            LinkedList 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) {
                            //中间
                            cur.next.prev = cur.prev;
                        }else {
                            //尾部
                            last = last.prev;
                        }
                    }
                    return;
                }
                cur=cur.next;
            }
        }
        //删除所有值为key的节点
        public void removeAllKey(int key){
            LinkedList 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) {
                            //中间
                            cur.next.prev = cur.prev;
                        }else {
                            //尾部
                            last = last.prev;
                        }
                    }
                }
                cur=cur.next;
            }
        }
        //得到的长度
        public int size(){
            int len = 0;
            LinkedList cur = head;
            while (cur!=null) {
                len++;
                cur=cur.next;
            }
            return len;
        }
        public void display(){
            LinkedList cur = head;
            while (cur!=null) {
                System.out.print(cur.val+" ");
                cur=cur.next;
            }
            System.out.println();
        }
        public void clear(){
            LinkedList cur = head;
            while (cur!=null) {
                LinkedList curNext = cur.next;
                cur.prev = null;
                cur.next = null;
                cur = curNext;
            }
            head=null;;
            last=null;
        }

}

三、ArrayList和LinkedList的区别

  1. 在存储空间上,ArrayList在物理上一定连续,LinkedList在逻辑上连续,但物理上不一定连续
  2. ArrayList支持随机访问,时间复杂度为O(1),但是LinkedList不支持,时间复杂度为O(N)
  3. ArrayList在头插时需要搬移元素,效率低O(N),LinkedList只需要修改引用的指向,时间复杂度为O(1)
  4. ArrayList在插入时空间不够时需要扩容,但是LinkedList没有容量的概念
  5. ArrayList应用于“元素高效存储和频繁访问”,LinkedList应用于“任意位置插入和删除频繁”

总结

以上就是今天要讲的内容,本文介绍了LinkedList的使用以及其模拟实现,最后我们对比了ArrayList和LinkedList。

你可能感兴趣的:(数据结构和算法,java,开发语言,链表,算法,数据结构)