一般使用「頭指針」來標識一個鏈表,頭指針始終指向鏈表的第一個結點。如單鏈表L,頭指針爲NULL的時表示一個空鏈表。下圖爲一個不帶頭結點的單鏈表,頭指針指向鏈表第一個結點,但結點1並非頭結點;html
在單鏈表的第一個結點以前附加一個結點,稱爲頭結點。頭結點的Data域能夠不存儲任何信息,也能夠記錄表長等相關信息。以下圖,就是一個含有頭結點的鏈表,此時頭指針指向頭結點;java
單鏈表只有一個指針域,在整個結點中數據域用來存儲數據元素,指針域用於指向下一個具備相同結構的結點,以下圖所示。node
與數組相似,單向鏈表中的節點也具備一個線性次序。以下圖所示,若是節點 1 的 next 引用指向節點2,則結點1就是結點2的直接前驅,結點2是結點1的直接後繼。即只能經過前驅節點找到後繼節點,而沒法從後繼節點找到前驅節點。數組
特色:數據結構
優勢:ide
缺點:oop
單鏈表的Java實現this
package com.victor.linkedlist; import java.util.Scanner; public class SingleLinkedListDemo { public static void main(String[] args) { SingleLinkedList sll = new SingleLinkedList(); char key = ' '; //接收用戶輸入 Scanner scanner = new Scanner(System.in); boolean loop = true; //輸出一個菜單欄 while(loop){ System.out.println("s(show): 打印鏈表"); System.out.println("a(add): 從尾部添加結點"); System.out.println("g(get): 刪除尾結點"); System.out.println("l(head): 輸出鏈表長度"); System.out.println("e(exit): 退出程序"); key = scanner.next().charAt(0); switch (key) { case 's': sll.showLinkedList(); break; case 'a': //從尾部添加結點 System.out.println("請輸入一個整數"); int value = scanner.nextInt(); sll.addFromTail(value); //最好判斷一下value是否是整數 break; case 'g': //刪除鏈表尾結點 try { int res = sll.getListNode();; System.out.printf("刪除的結點值爲%d\n", res); } catch (Exception e) { System.out.println(e.getMessage()); } break; case 'l': //輸出鏈表長度 System.out.printf("鏈表長度爲%d\n", sll.getLength()); break; case 'e': //退出 scanner.close(); loop = false; break; default: break; } } System.out.println("程序退出"); } } //定義結點類 class ListNode{ private int data; private ListNode next = null; //構造方法 public ListNode(int data) { this.data = data; } //返回data值 public int getData() { return this.data; } //設置data值 public void setData(int data) { this.data = data; } //返回下一個結點地址 public ListNode getNext() { return this.next; } //設置下一個結點地址 public void setNext(ListNode next) { this.next = next; } //重寫toString方法 @Override public String toString() { return "ListNode [data=" + data + "]"; } } //定義單鏈表類 class SingleLinkedList{ //頭結點 private ListNode head; //構造方法 public SingleLinkedList() { head = new ListNode(-1); } //頭插法添加結點 public void addFromHead(int data) { ListNode ListNode = new ListNode(data); //新建結點 ListNode curr = head.getNext(); head.setNext(ListNode); ListNode.setNext(curr); } //尾插法添加結點 public void addFromTail(int data) { ListNode ListNode = new ListNode(data); //新建結點 ListNode curr = head; while(curr.getNext() != null) { curr = curr.getNext(); } curr.setNext(ListNode); } //刪除鏈表尾結點 public int getListNode() { if (head.getNext() == null) { throw new RuntimeException("鏈表爲空鏈表"); } ListNode curr = head; ListNode prev = head; while(curr.getNext() != null) { prev = curr; curr = curr.getNext(); } prev.setNext(null); return curr.getData(); } //求鏈表長度 public int getLength() { int length = 0; ListNode curr = head; while(curr.getNext() != null) { length++; curr = curr.getNext(); } return length; } //打印鏈表 public void showLinkedList() { ListNode curr = head.getNext(); while(curr != null) { System.out.println(curr); curr = curr.getNext(); } } }
reference.net
深入理解:帶頭結點和不帶頭結點的區別 使用頭結點的優點https://blog.csdn.net/qq_24118527/article/details/81317410指針
鏈表詳解(易懂)https://blog.csdn.net/SlimShadyKe/article/details/89503062
韓順平數據結構
大話數據結構