真正的动态数据结构!
    概念:

    1. 是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针连接次序实现的。
    2. 每个链表都包含多个节点,节点包含两个部分。
      1. 数据域:存储节点含有的信息。
      2. 引用域:存储下一个节点或者上一个节点的地址。

    特点:

    • 获得数据麻烦,需要遍历查找,比数组慢。
    • 方便插入、删除。

    分类:

    1. 单向链表
    2. 双向链表
    3. 环形链表
    4. 双向环形链表

    1591605-20190129103112260-2048771825.png
    优点:
    真正的动态,不需要处理固定容量的问题。
    缺点:
    丧失了随机访问的能力。
    实现原理;

    1. 创建一个节点类。
      1. 数据域:链表中存储的信息。
      2. 节点域:相当于指针。单向链表有一个指针,指向下一个节点;双向链表有两个指针,分别指向上一个和下一个。
    2. 创建一个链表类。
      1. 头结点
      2. 为节点
      3. 大小

    单向链表节点类:

    1. public class Node{
    2. public Object data;
    3. public Node next;
    4. public Node(Object o){
    5. this.data = o;
    6. }
    7. }

    双向链表节点类:

    1. public class Node{
    2. public Object o;
    3. public Node next;
    4. public Node pre;
    5. public Node(Object o){
    6. this.o = o;
    7. this.next = null;
    8. this.next = null;
    9. }
    10. }

    设计一个简单链表

    1. //链表
    2. package com.qingFeng;
    3. public class LinkedList<E> {
    4. private class Node{
    5. public E e;
    6. public Node next;
    7. public Node(E e , Node next){
    8. this.e = e;
    9. this.next = next;
    10. }
    11. public Node(E e){
    12. this(e , null);
    13. }
    14. public Node() {
    15. this(null , null);
    16. }
    17. @Override
    18. public String toString(){
    19. return e.toString();
    20. }
    21. }
    22. //虚拟头节点
    23. private Node dummyHead;
    24. private int size;
    25. public LinkedList(){
    26. dummyHead = new Node(null,null);
    27. size = 0;
    28. }
    29. //获取链表中元素的个数
    30. public int getSize(){
    31. return size;
    32. }
    33. //返回链表是否为空
    34. public boolean isEmpty(){
    35. return size == 0;
    36. }
    37. //在链表头添加新的元素e
    38. public void addFirst(E e){
    39. /*Node node = new Node(e);
    40. node.next = head;
    41. head = node;*/
    42. add(0,e);
    43. }
    44. //在链表中间添加元素e
    45. public void add(int index, E e){
    46. if (index < 0 || index > size){
    47. throw new IllegalArgumentException("add failed. Illegal index.");
    48. }
    49. Node prev = dummyHead;
    50. for (int i = 0 ; i < index ; i ++){
    51. prev = prev.next;
    52. }
    53. /*Node node = new Node(e);
    54. node.next = prev.next;
    55. prev.next = node;*/
    56. prev.next = new Node(e,prev.next);
    57. size ++;
    58. }
    59. //在链表末尾添加新的元素e
    60. public void addLast(E e){
    61. add(size, e);
    62. }
    63. //获取链表的第index位置的元素
    64. public E get(int index){
    65. if (index < 0 || index >= size){
    66. throw new IllegalArgumentException("Get failed. Illegal index.");
    67. }
    68. Node cur = dummyHead.next;
    69. for (int i = 0 ; i < index ; i ++){
    70. cur = cur.next;
    71. }
    72. return cur.e;
    73. }
    74. //获取链表的第一个元素
    75. public E getFirst(){
    76. return get(0);
    77. }
    78. //获取链表最后一个元素
    79. public E getLast(){
    80. return get(size - 1);
    81. }
    82. //修改链表第index位置的元素为e
    83. public void set(int index , E e){
    84. if (index < 0 || index >= size){
    85. throw new IllegalArgumentException("Set failed. Illegal index.");
    86. }
    87. Node cur = dummyHead.next;
    88. for (int i = 0 ; i < index ; i ++){
    89. cur = cur.next;
    90. }
    91. cur.e = e;
    92. }
    93. //查找链表中是否有元素e
    94. public boolean contains(E e){
    95. Node cur = dummyHead.next;
    96. while (cur != null){
    97. if (cur.e.equals(e)){
    98. return true;
    99. }
    100. cur = cur.next;
    101. }
    102. return false;
    103. }
    104. //从链表中删除index位置的元素,返回删除的元素
    105. public E remove(int index){
    106. if (index < 0 || index >= size){
    107. throw new IllegalArgumentException("Remove failed. Index is illegal");
    108. }
    109. Node prev = dummyHead;
    110. for (int i = 0 ; i < index ; i ++){
    111. prev = prev.next;
    112. }
    113. Node retNode = prev.next;
    114. prev.next = retNode.next;
    115. retNode.next = null;
    116. size --;
    117. return retNode.e;
    118. }
    119. //从链表中删除第一个元素
    120. public E removeFirst(){
    121. return remove(0);
    122. }
    123. //从链表删除最后一个元素
    124. public E removeLast(){
    125. return remove(size - 1);
    126. }
    127. @Override
    128. public String toString(){
    129. StringBuilder res = new StringBuilder();
    130. /*Node cur = dummyHead.next;
    131. while (cur != null){
    132. res.append(cur + "——>");
    133. cur = cur.next;
    134. }*/
    135. for (Node cur = dummyHead.next ; cur != null ; cur = cur.next){
    136. res.append(cur + "——>");
    137. }
    138. res.append("null");
    139. return res.toString();
    140. }
    141. }
    142. //客户端
    143. package com.qingFeng;
    144. public class Main {
    145. public static void main(String[] args) {
    146. LinkedList<Integer> linkedList = new LinkedList<>();
    147. for (int i = 0 ; i < 5 ; i ++){
    148. linkedList.addLast(i);
    149. }
    150. System.out.println(linkedList);
    151. linkedList.remove(1);
    152. System.out.println(linkedList);
    153. linkedList.removeLast();
    154. System.out.println(linkedList);
    155. }
    156. }