Java中我們使用的ArrayList,其實現原理是數組。而LinkedList的實現原理就是鏈表了。鏈表在進行循環遍歷時效率不高,但是插入和刪除時優勢明顯。
說明:以下代碼是按照自己理解實現,有不正確的地方,請批評指正!!
1. 定義結點類
class ListNode {
int val;
ListNode next = null;
ListNode(int val) {
this.val = val;
}
}
2. 建表(尾插法)
思路:
頭插法建立鏈表雖然算法簡單,但生成的鏈表中結點的次序和輸入的順序相反。若希望二者次序一致,可采用尾插法建表。該方法是將新結點插入到當前鏈表的表尾上,為此必須增加一個尾指針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;
}
3. 打印鏈表
// 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
4. 插入結點
// 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;
}
5. 刪除結點
// 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;
}
6. 總代碼
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;
}
}