手写一个简单的单链表的增删改查, 本文不注重代码的严谨格式等, 仅仅是探究其实现的思想

假如我们需要添加一个数据

代码中数据结构是这样的

1
2
3
4
5
6
7
8
class Node {
    // 存储下一个节点
    Node next;
    String mes;
    public Node(String mes) {
        this.mes = mes;
    }
}

插入

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
public static void insert(Node n) {
        Node current = rootNode;

        if (current == null) {
            // 第一次插入
            rootNode = n;
            return;
        }

        Node next;
        while ((next = current.getNext()) != null) {
            current = next; // 移动指针
        }
        current.setNext(n);
    }

删除

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
 public static void delete(String mes) {
        Node current = rootNode;

        Node next;
        // 1, 2, 3, 4, 5
        // 假如是要删除3, 则需要2的指针链上4
        // 因为单链表找不到前驱节点, 所以需要先找到2所在的当前节点, 然后删除3,找到3所在的节点的下一个节点指向2
        while ((next = current.getNext()) != null) {

            if (mes.equals(next.getMes())) {
                // 删除节点, 指针位置发生改变
                current.setNext(next.getNext());  // 2 = 4
                next.setNext(null); // 3 // 原本3的指向移除掉
                return;
            }
            current = next;
        }
    }

修改

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
 public static void modify(String oldMes, String newMes) {
        Node current = rootNode;

        Node next;
        // 1, 2, 3, 4, 5
        // 假如要修改的是3,改为 6

        while ((next = current.getNext()) != null) {
            if (oldMes.equals(current.getMes())) {
                current.setMes(newMes);
                return;
            }
            current = next;
        }
    }

获取

1
2
3
4
5
6
7
8
9
    public static void getAll() {
        Node current = rootNode;
        Node next;
        while ((next = current.getNext()) != null) {
            System.out.println(current.getMes());
            current = next;
        }
        System.out.println(current.getMes());
    }

完整代码如下

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
public class MyTest {

    private static Node rootNode = null;

    public static void insert(Node n) {
        Node current = rootNode;

        if (current == null) {
            // 第一次插入
            rootNode = n;
            return;
        }

        Node next;
        while ((next = current.getNext()) != null) {
            current = next; // 移动指针
        }
        current.setNext(n);
    }

    public static void delete(String mes) {
        Node current = rootNode;

        Node next;
        // 1, 2, 3, 4, 5
        // 假如是要删除3, 则需要2的指针链上4
        // 因为单链表找不到前驱节点, 所以需要先找到2所在的当前节点, 然后删除3,找到3所在的节点的下一个节点指向2
        while ((next = current.getNext()) != null) {

            if (mes.equals(next.getMes())) {
                // 删除节点, 指针位置发生改变
                current.setNext(next.getNext());  // 2 = 4
                next.setNext(null); // 3 // 原本3的指向移除掉
                return;
            }
            current = next;
        }
    }

    public static void modify(String oldMes, String newMes) {
        Node current = rootNode;

        Node next;
        // 1, 2, 3, 4, 5
        // 假如要修改的是3,改为 6

        while ((next = current.getNext()) != null) {
            if (oldMes.equals(current.getMes())) {
                current.setMes(newMes);
            }
            current = next;
        }
    }

    public static void getAll() {
        Node current = rootNode;

        Node next;
        while ((next = current.getNext()) != null) {
            System.out.println(current.getMes());
            current = next;
        }
        System.out.println(current.getMes());
    }

    public static void main(String[] args) {

        Node node = new Node("1");
        Node node1 = new Node("2");
        Node node2 = new Node("3");
        Node node3 = new Node("4");
        Node node4 = new Node("5");

        insert(node);
        insert(node1);
        insert(node2);
        insert(node3);
        insert(node4);

        delete("3");
        modify("3", "6");

        getAll();

    }

}

class Node {
    // 存储下一个节点
    private Node next;

    private String mes;

    public Node(String mes) {
        this.mes = mes;
    }

    public Node getNext() {
        return next;
    }

    public void setNext(Node next) {
        this.next = next;
    }

    public String getMes() {
        return mes;
    }

    public void setMes(String mes) {
        this.mes = mes;
    }
}

好了, 增删改查的代码大致就是这些了, 在 ArrayList源码分析 中我们了解到其内部使用的是数组的结构, 或者叫顺序表的方式, 那么他们两个到底有什么区别呢 ? 或者是在使用场景上有什么区别呢 ?

首先针对数据的增删改查来说, 顺序表的内存地址是连续的, 他可以基于下标快速访问到元素,这是优点, 删除元素需要一直遍历查找到元素为止, 然后一个一个到挪动元素的位置, 消耗时间

相对于顺序表, 单链表的优点是, 内存地址是不连续的, 当前节点存在着下一个节点的引用, 直接修改节点引用即可, 复杂度相对于顺序表简单

所以查找到使用顺序表结构, 修改多使用链表的形式