你们用LinkedList吗?原作者都不用

1,338 阅读2分钟

聊聊LinkedList

不知道你们用过LinkedList没,对于LinkedList的印象我可能停留在2个地方:

1、java八股文中,比如ArryList和LinkedList的区别,ArrayList支持随机访问,能根据下标查询,但从中间插入或删除需要移动移动数组;LinkedList插入删除快,但不支持随机访问,而且占用内存比较大。HashMap底层运用了LinkedList拉链法解决Hash冲突......

2、leetCode的链表操作,如合并链表,反转链表,删除链表倒数第N个节点......

那么问题来了,LinkedList真的好用吗,我问了几个同事都说在工作中没用过LinkedList,基本上数组用ArrayList就能解决问题,连原作者在推特上也说自己写了也没用过

1685878464995.png

但是不用归不用,对于链表的简单操作和数据结构最好还是要了解熟悉,万一面试问到了或者机试考到了呢

简单链表操作

image.png

第一个接触链表简单题是合并两个有序列表,一开始是没啥想法..对链表操作不太熟悉,后面看了答案之后发现好像也不难,但是自己写又写不出来- -答案的思路是先建立一个头结点,比较两个链表节点哪个小就连接哪个节点,如果某个链表遍历完了,就连接另一个链表。

image.png

上面用的尾插法,通过node = node.next移动末尾,再用node.next = newNode插入,注意先用一个head标记头指针,不然无法找到他的头指针。

看过HashMap八股文应该知道jdk1.7多线程rehash会有循环列表问题,涉及到头插法,简单说一下头插法实现:

newNode.next = oldNode;
oldNode = newNode;

一开始我看代码的时候感觉头晕脑胀,怎么指来指去的?后面画了一个图后,逻辑就比较清晰明了

image.png

堆栈与队列

在看算法的时候发现堆栈与队列的实现方式也是很巧妙的,使用了头插法和尾插法的方式。

堆栈: 头插法添加元素

public class Stack<Item> 
{
    private Node first;//栈顶,最近添加的元素
    private int N; //元素数量
    private class Node{
        Item item;
        Node next;
    }
    public void push(Item item){
        //栈顶添加元素
        Node oldfirst = first;
        first = new Node();
        first.next = oldfirst;
        N++;
    }
    public Item pop() {
        //栈顶弹出元素
        Item item = fist.item;
        first = first.next;
        N--;
        return item;
    }
}

队列: 尾插法添加元素,需要记录头结点和尾节点


public class Queue<Item>{
    private Node first;//头结点
    private Node last; //尾节点
    private int n;
    private class Node {
        Item item;
        Node next;
    }
    public void enqueue(Item item) {
        Node oldlast =last;
        last = new Node();
        last.item = item;
        last.next = null;
        if(isEmpty()) first = last;
        else oldlast.next = last;
        N++;
        
    }
}