Java單鏈表實現
單鏈表各位置插入結點
單鏈表各位置刪除結點
單鏈表正逆向遍曆結點
單鏈表是實現棧、隊列、雜湊表等多種資料結構的基礎,在此總結一下Java單鏈表中不同位置插入節點、不同位置刪除結點、正逆向遍曆結點的方法,以備以後複習時用。本人菜鳥一枚,如有錯誤請各位大佬批評指正。 單鏈表插入結點,根據插入位置不同可以分為: 在頭結點處插入結點,時間複雜度o(1),addFirst(int val) 在尾結點處插入結點,時間複雜度o(n),addLast(int val) 在任意位置插入結點,時間複雜度o(n),add(int index,int val) 單鏈表刪除結點,根據插入位置不同可以分為: 在頭結點處刪除結點,時間複雜度o(1),deleteFirst() 在尾結點處刪除結點,時間複雜度o(n),deleteLast() 在任意位置刪除結點,時間複雜度o(n),delete(int index,int val) 單鏈表的遍曆: 正向遍曆,display() 逆向遍曆,displayFromTail()
採用單鏈表實現棧(先入後出)的功能,可以採用addFirst()和deleteLast()方法封裝為push()和pop()方法;
採用單鏈表實現隊列(先入先出)的功能,可以採用addFirst()和deleteFirst()方法封裝為enqueue()和dequeue()方法;
代碼如下:
package chapter.two.bean;public class ListNode { /*** * 結點內部類 * @author Janet * */ private class Node{ int val; Node next; Node(int val) { this.val = val; } } //私人欄位 private Node first = null; private int N = 0; /*** * 判斷鏈表是否為空白 * @return */ public boolean isEmpty() { return N==0; } /** * 返回鏈表結點數 * @return */ public int size() { return N; } /*** * 在頭結點處添加元素,時間複雜度o(1) * @param val */ public void addFirst(int val) { if( isEmpty() ) { first = new Node(val); first.next = null; } else { Node newFirst = new Node(val); newFirst.next = first; first = newFirst; } N++; } /*** * 在鏈表結尾處添加元素,時間複雜度o(n) * @param val */ public void addLast(int val) { if( isEmpty() ) { first = new Node(val); first.next = null; } else { Node p = first; while( p.next != null ) { p = p.next; } //p為尾結點 p.next = new Node(val); p.next.next = null; } N++; } /*** * 在任意位置添加元素,時間複雜度o(n) * @param index * @param val * @throws Exception */ public void add(int index,int val) throws Exception { if( index>=size() || index<0 ) { throw new Exception("鏈表不存在該位置"); } else { if( index==0 ) { addFirst(val); return; } Node p = first; for (int i = 1; i < index; i++) { p = p.next; } //在p處添加新節點 Node q = new Node(val); q.next = p.next; p.next = q; N++; } } /*** * 刪除頭結點並返回,時間複雜度o(1) * @return */ public Node deleteFirst() { Node result = first; first = first.next; N--; return result; } /*** * 刪除最後一個結點並返回,時間複雜度o(1) * @return */ public Node deleteLast() { Node p = first; while( p.next.next != null ) { p = p.next; } //要刪除p.next Node result = p.next; p.next = null; N--; return result; } /*** * 刪除任意位置的結點並返回,時間複雜度o(n) * @param index * @return * @throws Exception */ public Node delete(int index) throws Exception { if( index<0 || index>=size() ) { throw new Exception("鏈表不存在該位置"); } else { if( index==0 ) { N--; return deleteFirst(); } else { Node p = first; for (int i = 1; i < index-1; i++) { p = p.next; } //p.next(q)為要刪除的結點 Node q = p.next; p.next = q.next; q.next = null; N--; return q; } } } /*** * 正向遍曆鏈表 */ public void display() { for (Node temp = first; temp!=null; temp=temp.next) System.out.println(temp.val); } /*** * 逆向遍曆鏈表 */ public void displayFromTail() { displayFromTail(first); } private void displayFromTail(Node p) { if( p != null ) { if( p.next != null ) { displayFromTail(p.next); } System.out.println(p.val); } }}
ListNode鏈表類中定義了私人欄位 Node first:頭結點 N:鏈表中結點個數,通過方法size()擷取
在任意位置的插入刪除中,約定鏈表的位置(index)從0開始 關於逆向遍曆鏈表 參考劍指offer面試題5:從尾到頭列印鏈表
要逆向遍曆鏈表,可以考慮正向遍曆鏈表,並依次把結點元素存到棧中,由於棧是遞迴的一種形式,可以由此想到用遞迴來解決。如果結點p有next域,就遞迴調用displayFromTail(p.next)即可。