1. 什么是链表

链表是线性表的一种。线性表就是字面意思,数据之间的关系被一条线所串联。

线性表又分为地址空间连续的地址空间不连续两种。

如数组就是地址空间连续线性表,他们在内存中是一块连续的数据块,块与块之间紧挨着,就好比X轴上的[-1,0,1]的关系一样。

而链表则是地址空间不连续的线性表,他们在内存中不是连续的块,而是分散在各处,然后通过一条弯曲的线串起来了。

以下就是比较形象的描述了。

  • 地址空间连续线性表:

    |😀 |😂|😆|🙃|😉|

  • 地址空间不连续线性表

    😀---------->😂------->😆--->🙃------------>🙃>😉

2. 链表特点

链表分为单链表和双链表。单链表就是只知道下一个节点的位置(上图是单链表),而双链表则可以知道上一个和下一个节点的位置。

单链表上的每个节点包含两部分,一部分是链表节点上的数据,另一部分则是指向下一个节点的线(指针)。

双链表上的每个节点包含三部分,一部分是链表节点上的数据,一部分是指向下一个节点的线(指针),还有一部分则是指向上一个节点的线(指针)。

链表的基本操作

  • 新增节点:在开头、中间和末尾
  • 删除节点:在开头、中间和结尾
  • 查询节点:查询第i个位置的节点数据

3. java实现(双链表)

public class LinkedList<E> implements List<E>, Queue<E>, Stack<E> {

    private int size = 0;

    private Node<E> head;
    private Node<E> tail;


    public LinkedList() {
        tail = head = null;
    }

    @Override
    public boolean isEmpty() {
        return size() == 0;
    }

    @Override
    public int size() {
        return size;
    }

    @Override
    public boolean add(E e) {
        return offer(e);
    }

    @Override
    public boolean remove(E e) {
        Node<E> tmp = head;
        int idx = 0;
        while (tmp != null) {
            if (tmp.e.equals(e)) {
                remove(idx);
                return true;
            }
            idx++;
            tmp = tmp.next;
        }
        return false;
    }

    @Override
    public boolean contains(E e) {
        Node<E> tmp = head;
        while (tmp != null) {
            if (tmp.e.equals(e)) {
                return true;
            }
            tmp = tmp.next;
        }
        return false;
    }

    @Override
    public E get(int i) {
        if (i > size) {
            throw new IndexOutOfBoundsException("Index i " + i + "out of range " + size);
        }
        if (i == 0) {
            return head.e;
        }
        if (i == size - 1) {
            return tail.e;
        }
        Node<E> tmp = head;
        for (int j = 0; j < i; j++) {
            tmp = tmp.next;
        }
        return tmp.e;
    }

    @Override
    public E remove(int i) {
        if (i >= size) {
            throw new IndexOutOfBoundsException("Index i " + i + "out of range " + size);
        }
        if (i == 0) {
            return poll();
        }
        if (i == size - 1) {
            return pop();
        }
        Node<E> tmp = head;
        for (int j = 0; j < i; j++) {
            tmp = tmp.next;
        }
        E e = tmp.next.e;
        tmp.next.next.prev = tmp;
        tmp.next = tmp.next.next;
        return e;
    }

    @Override
    public boolean add(E e, int i) {
        if (i > size) {
            throw new IndexOutOfBoundsException("Index i " + i + "out of range " + size);
        }
        Node<E> node = new Node<>(e);
        if (i == size) {
            return offer(e);
        }
        if (i == 0) {
            node.next = head;
            node.prev = null;
            head = node;
        } else {
            Node<E> tmp = head;
            for (int j = 0; j <= i; j++) {
                tmp = tmp.next;
            }
            tmp.next = node;
            node.prev = tmp;
        }
        size++;
        return false;
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append("LinkedList: { ");
        Node<E> node = head;
        while (node != null) {
            sb.append(node.e).append("<->");
            node = node.next;
        }
        sb.append("null }");
        return sb.toString();
    }

    private static class Node<E> {

        E e;

        Node<E> next;
        Node<E> prev;

        public Node(E e) {
            this.e = e;
        }
    }

}

4. 数据结构系列代码地址

个人还实现了其他数据结构和算法,感兴趣的伙伴可以到Github或博客上查看详细完整代码和测试。

Githubhttps://github.com/bennetty74...

Bugkit bloghttp://bugkit.cnIP


benntty74
49 声望0 粉丝

小透明