手寫雙向連結串列
阿新 • • 發佈:2018-12-30
採用雙向連結串列的形式嘗試寫一下 java中LinkedList
public class LinkedList<E> { /** * 節點 */ private static class Node<E> { E item; Node<E> pre; Node<E> next; public Node(Node<E> pre, E item, Node<E> next) { this.item = item; this.pre = pre; this.next = next; } } public LinkedList() { } //頭節點 Node<E> first; //尾節點 Node<E> last; //大小 int size; /** * 新增資料在最後 */ public void add(E e) { linkLast(e); } /** * 新增到最後 * * @param e */ private void linkLast(E e) { Node<E> newNode = new Node<>(last, e, null); Node<E> temp = last; last = newNode; if (temp == null) { first = newNode; } else { temp.next = newNode; } size++; } /** * 獲取物件 */ public E get(int index) { if (index < 0 || index > size - 1) { return null; } return node(index).item; } /** * 獲取index位置上的節點 * * @param index */ private Node<E> node(int index) { Node<E> node; //如果index在連結串列前半部分 if (index < (size >> 1))//除以2 { node = first; for (int i = 0; i < index; i++) { node = node.next; } } else { node = last; for (int i = size - 1; i > index; i--) { node = node.pre; } } return node; } /** * 新增資料在index位置 */ public void add(int index, E e) { if (index < 0 || index > size) { return; } if (index == size) { linkLast(e); } else { Node<E> target = node(index); Node<E> preNode = target.pre; Node<E> newNode = new Node<>(preNode, e, target); if (preNode == null) { first = newNode; target.pre = newNode; } else { preNode.next = newNode; target.pre = newNode; } size++; } } /** * 刪除元素 */ public void remove(int index) { if (size == 0 || index < 0 || index > size - 1) { return; } Node<E> node = node(index); unLinkNode(node); } private void unLinkNode(Node<E> node) { Node<E> preNode = node.pre; Node<E> nextNode = node.next; if (preNode == null) { first = nextNode; } else if (nextNode == null) { last = preNode; } else { preNode.next = nextNode; nextNode.pre = preNode; } size--; } }
寫個test測試下功能
@Test public void testLinkedList(){ LinkedList<Integer> list=new LinkedList<>(); list.add(3); list.add(80); list.add(1); list.add(7); list.add(32); log(list); list.add(0,12); log(list); list.add(3,50); log(list); list.remove(3); log(list); list.remove(0); log(list); } public void log(LinkedList linkedList){ for (int i = 0; i < linkedList.size; i++) { System.out.print(linkedList.get(i)+" "); } System.out.println(""); }
列印結果
3 80 1 7 32
12 3 80 1 7 32
12 3 80 50 1 7 32
12 3 80 1 7 32
3 80 1 7 32
判斷單鏈表是否存在環?
【快慢指標】:需要兩個指標,一個快指標:每次走兩步,一個慢指標:每次走一步。
如果快慢指標能夠相遇(如果快指標能夠追上慢指標),就證明有環。
但是!!!這個方法存在問題。如果連結串列夠長,而環又足夠小,那麼快指標將永遠不會追上慢指標
所以,快慢指標只適合用於環出現在連結串列尾部的情況,也就是單鏈表環的問題,而無法解決連結串列存在迴圈的問題。
public class Link_list_circle { public boolean hascycle(ListNode head) { //快慢指標 ListNode slow, fast; slow = fast = head; while (fast != null && fast.next != null) { slow = slow.next; fast = fast.next.next; if (fast == slow) return ture; } return false; } }