1. 程式人生 > >《資料結構與演算法》之連結串列—單向連結串列

《資料結構與演算法》之連結串列—單向連結串列

連結串列(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();
	}