《資料結構與演算法》之連結串列—單向連結串列
阿新 • • 發佈:2018-11-10
連結串列(LinkedList)
連結串列是一種物理儲存單元上非連續、非順序的儲存結構,資料元素的邏輯順序是通過連結串列中的指標連結次序實現的。連結串列由一系列節點(連結串列中每一個元素稱為節點)組成,節點可以在執行時動態生成。每個節點包括兩個部分:一個是儲存資料元素的資料域,另一個是儲存下一個節點地址的指標域。
相比於線性表順序結構,連結串列操作複雜。由於不必須按順序儲存,連結串列在插入的時候可以達到O(1)的複雜度,比另一種線性表順序錶快得多,但是查詢一個節點或者訪問特定編號的節點則需要O(n)的時間,線性表和順序表相應的時間複雜度分別是O(logn)和O(1)。
連結串列分為單鏈表和雙向連結串列。
1、單向連結串列(Single-Linked List)
單鏈表是連結串列中結構最簡單的。一個單鏈表的節點(Node)分為兩個部分,第一個部分也就是資料部分,儲存關於節點的資料資訊,另一個部分則儲存下一個節點的地址。當然,最後一個節點儲存地址的部分指向空值。
對於單向連結串列,我們只可以單方向進行遍歷,也就是從頭節點往後依次訪問後面的節點,一直訪問到需要的位置。而插入一個節點,則只能在連結串列頭插入,只需要將當前插入的節點設定為頭節點,next指向原頭節點可。刪除一個節點,需要將該節點的上一個節點的next指向該節點的下一個節點。
public class SingleLinkedList { private int size;//連結串列節點的個數 private Node head;//連結串列的頭節點 //連結串列建構函式 public SingleLinkedList(){ size = 0; head = null; } //連結串列的節點類 private class Node{ private Object data;//每個節點的資料 private Node next;//每個節點指向下一個節點的連線 public Node(Object data){ this.data = data; } } //在連結串列頭新增元素 public Object addHead(Object obj){ Node newHead = new Node(obj); if(size == 0){ head = newHead; }else{ newHead.next = head; head = newHead; } size++; return obj; } //在連結串列頭刪除元素 public Object deleteHead(){ Object obj = head.data; head = head.next; size--; return obj; } //查詢指定元素,找到了返回節點Node,找不到返回null public Node find(Object obj){ Node current = head; int tempSize = size; while(tempSize > 0){ if(obj.equals(current.data)){ return current; }else{ current = current.next; } tempSize--; } return null; } //刪除指定的元素,刪除成功返回true public boolean delete(Object value){ if(size == 0){ return false; } Node current = head; Node previous = head; while(current.data != value){ if(current.next == null){ return false; }else{ previous = current; current = current.next; } } //如果刪除的節點是第一個節點 if(current == head){ head = current.next; size--; }else{ //如果刪除的節點不是第一個節點 previous.next = current.next; size--; } return true; } //判斷連結串列是否為空 public boolean isEmpty(){ return (size == 0); } //顯示節點資訊 public void display(){ if(size >0){ Node node = head; int tempSize = size; if(tempSize == 1){//當前連結串列只有一個節點 System.out.println("["+node.data+"]"); return; } while(tempSize>0){ if(node.equals(head)){ System.out.print("["+node.data+"->"); }else if(node.next == null){ System.out.print(node.data+"]"); }else{ System.out.print(node.data+"->"); } node = node.next; tempSize--; } System.out.println(); }else{//如果連結串列一個節點都沒有,直接列印[] System.out.println("[]"); } } }
測試程式程式碼如下:
public static void SingleLinkedListTest(){ SingleLinkedList singleList = new SingleLinkedList(); singleList.addHead("1"); singleList.addHead("2"); singleList.addHead("3"); singleList.addHead("4"); //列印當前連結串列資訊 singleList.display(); //刪除3 singleList.delete("3"); singleList.display(); //查詢4 System.out.println(singleList.find("4")); }
用單向連結串列實現棧,其中棧的pop()方法和push()方法,分別可以用頭部刪除元素方法deleteHead()以及頭部增加元素方法addHead()實現。
public class StackSingleLink {
private SingleLinkedList link;
public StackSingleLink() {
link = new SingleLinkedList();
}
// 新增元素
public void push(Object obj) {
link.addHead(obj);
}
// 移除棧頂元素
public Object pop() {
Object obj = link.deleteHead();
return obj;
}
// 判斷是否為空
public boolean isEmpty() {
return link.isEmpty();
}
// 列印棧內元素資訊
public void display() {
link.display();
}
}
測試程式程式碼:
private static void StackSingleLinkTest() {
StackSingleLink linklist=new StackSingleLink();
linklist.push("123");
System.out.println(linklist.isEmpty());
linklist.display();
linklist.pop();
System.out.println(linklist.isEmpty());
linklist.display();
}