Java中咱们使用的ArrayList,其实现原理是数组。而LinkedList的实现原理就是链表了。链表在进行循环遍历时效率不高,可是插入和删除时优点明显。java
说明:如下代码是按照本身理解实现,有不正确的地方,请批评指正!!算法
class ListNode { int val; ListNode next = null; ListNode(int val) { this.val = val; } }
思路: 头插法创建链表虽然算法简单,但生成的链表中结点的次序和输入的顺序相反。若但愿两者次序一致,可采用尾插法建表。该方法是将新结点插入到当前链表的表尾上,为此必须增长一个尾指针tail,使其始终指向当前链表的尾结点。
// 1. 建立单链表(尾插法建表) public static ListNode createList(int[] arr) { ListNode head = new ListNode(arr[0]); // 头结点 ListNode tail = head; for (int i = 1; i < arr.length; i++) { ListNode newNode = new ListNode(arr[i]); tail.next = newNode; tail = newNode; } return head; }
// 2. 打印链表 public static void printList(ListNode head) { while (head != null) { if (head.next == null) System.out.println(head.val); else System.out.print(head.val + " --> "); head = head.next; } } // 输出结果: 11 --> 22 --> 33 --> 44 --> 55
// 3. 在建好的链表中的第k个位置插入一个值为val的结点 public static ListNode insertNode(ListNode head, int k, int val) { ListNode preNode = head; // 临时指针,用于指向要插入位置的前一个结点 if (k < 1) return head; if (k == 1) // 若是在第一个位置插入(将插在第1个结点以前) { ListNode newNode = new ListNode(val); // 建立该结点 newNode.next = preNode; head = newNode; return head; } while (k-- > 2) // 使preNode指向第k个位置的前一个结点 { preNode = preNode.next; } ListNode newNode = new ListNode(val); // 建立该新结点 // 插入 newNode.next = preNode.next; preNode.next = newNode; return head; }
// 4. 删除结点(删除第k个结点) public static ListNode delNode(ListNode head, int k) { ListNode preNode = head; // 临时指针,用于指向要删除位置的前一个结点 if (k < 1) // 不删任何结点 return head; if (k == 1) // 删除第一个结点 { head = head.next; // 将指针日后移动一位就至关于删除了第一个结点 return head; } while (k-- > 2) // 使preNode指向第k个结点的前面一个结点 { preNode = preNode.next; } // 删除结点(经过跳过待删除结点来实现删除结点的效果) preNode.next = preNode.next.next; return head; }
class ListNode { int val; ListNode next = null; ListNode(int val) { this.val = val; } } public class Main { public static void main(String[] args) { int[] arr = {11, 22, 33, 44, 55}; ListNode head = createList(arr); // 建表 // 打印链表 printList(head); // 插入 // //head = insertNode(head, 1, 99); // 在第一个位置插入99 // head = insertNode(head, 3, 99); // 在第3个位置插入99 // printList(head); // 删除 head = delNode(head, 2); // 删除地2个结点 printList(head); } // 1. 建立带头结点的单链表(尾插法建表) public static ListNode createList(int[] arr) { ListNode head = new ListNode(arr[0]); // 头结点 ListNode tail = head; for (int i = 1; i < arr.length; i++) { ListNode newNode = new ListNode(arr[i]); tail.next = newNode; tail = newNode; } return head; } // 2. 打印链表 public static void printList(ListNode head) { while (head != null) { if (head.next == null) System.out.println(head.val); else System.out.print(head.val + " --> "); head = head.next; } } // 3. 在建好的链表中的第k个位置插入一个值为val的结点 public static ListNode insertNode(ListNode head, int k, int val) { ListNode preNode = head; // 临时指针,用于指向要插入位置的前一个结点 if (k < 1) return head; if (k == 1) // 若是在第一个位置插入(将插在第1个结点以前) { ListNode newNode = new ListNode(val); // 建立该结点 newNode.next = preNode; head = newNode; return head; } while (k-- > 2) // 使preNode指向第k个位置的前一个结点 { preNode = preNode.next; } ListNode newNode = new ListNode(val); // 建立该新结点 // 插入 newNode.next = preNode.next; preNode.next = newNode; return head; } // 4. 删除结点(删除第k个结点) public static ListNode delNode(ListNode head, int k) { ListNode preNode = head; // 临时指针,用于指向要删除位置的前一个结点 if (k < 1) // 不删任何结点 return head; if (k == 1) // 删除第一个结点 { head = head.next; // 将指针日后移动一位就至关于删除了第一个结点 return head; } while (k-- > 2) // 使preNode指向第k个结点的前面一个结点 { preNode = preNode.next; } // 删除结点(经过跳过待删除结点来实现删除结点的效果) preNode.next = preNode.next.next; return head; } }