數據結構與算法經典問題解析-Java語言描述(第三章鏈表(後半部分))

2020年2月27日
最近因一些原因導致關於大前端的學習筆記沒有再更新,因爲本人馬上要畢業了,遇到許多煩心事,就業,畢業設計等,總的來說就是一句話,以前的3年半浪費了,所以現在慌了,最好決定先把畢業設計做好,因爲我選的畢業設計和Java的關聯比較多,並且我也是比較喜歡Java的,所以先把這一門好好學學,最近會更新和Java有關的筆記,前端的學習先放一下,不過早晚我會在拾起來的,畢竟我是要做全棧工程師的男人,希望大家不要因此放棄我,O(∩_∩)O!
1.雙向鏈表
1.1雙向鏈表的優缺點
優點:
對於鏈表中一個給定的結點,可以從兩個方向進行操作。在單向鏈表中,只有獲得結點的前驅結點的指針,才能刪除該結點。然而,在雙向鏈表中,即使沒有一個結點的前驅結點的地址,也能刪除該結點(因爲每個結點有都一個指向前驅
結點的指針,可以直接後退到前驅結點)。
主要的缺點:
●每個結點需再添加一個額外的指針,因此需要更多的空間開銷。
●結點的插人或刪除更加費時(需要更多的指針操作)。
1.2雙向鏈表的類型聲明

public class DLLNode{
		private int data;
		private DLLNode next;
		private DLLNode previous;
		public DLLNode(int data){
			this.data = data;
		}
		public void setData(int data){
			this.data = data;
		}
		public int getData(){
			return data;
		}
		public void setNext(DLLNode next){
			this.next = next;
		}
		public DLLNode getNext(){
			return this.next;
		}
		public void setPrevious(DLLNode previous){
			this.previous = previous;
		}
		public DLLNode getPrevious(){
			return this.previous;
		}
}
			

1.3插入結點代碼

	DLLNode DLLInsert(DLLNode headNode, DLLNode nodeToInsert, int position){
		if(headNode == null)
		//最初鏈表爲空時插入
			return nodeToInsert;
		int size = getDLLLength(headNode);
		if(position > size+1 || position < 1){
			System.out.println("插入位置無效 " + "有效插入位置爲 1至"+(size+ 1));
			return headNode;
		}
		if(position == 1){//在鏈表開頭插入
			nodeToInsert. setNext(headNode);
			headNode. setPrevious(nodeToInsert);
			return nodeToInsert;
		}else{
		//在鏈表中間或末尾插入
			DLLNode previousNode = headNode;
			int count = 1;
			while(count < position-1){
				previousNode = previousNode.getNext();
				count++;
			}
		DLLNode currentNode = previousNode.getNext();
		nodeToInsert.setNext(currentNode);
		if(currentNode != null)
			currentNode.setPrevious(nodeToInsert);
		previousNode.setNext(nodeToInsert);
		nodeToInsert.setPrevious(previousNode);
		}
		return headNode;
	}

時間複雜度爲O(n)。在最差情況下,需要在鏈表的尾部插入結點。
空間複雜度爲0(1),用於創建臨時變量。

1.4刪除結點代碼

	DLLNode DLLDelete(DLLNode headNode, int position){
		int size = getDLLLength(headNode);
		//如果被刪除位置不在鏈表長度範圍內,報錯並返回
		if(position > size || position < 1){
			System.out. println("該刪除位置無效,有效位置爲 1至"+size);
			return headNode;
			}
		if(position == 1){// 刪除鏈表的第一個結點
			DLLNode currentNode = headNode.getNext();
			headNode = null;
			currentNode.setPrevious(null);
			return currentNode;
		}else{
			//刪除中間或表尾結點
		DLLNode previousNode = headNode;
		int count= 1;
		while(count < position-1){
			previousNode = previousNode.getNext); 
			count++; 
		}
		DLLNode currentNode = previousNode.getNext();
		DLLNode laterNode = currentNode.getNext();
		previousNode.setNext(laterNode);
		if(laterNode != null)
			//如果被刪除結點的後繼結點不是NULL結點,那麼設置其前驅.
			//指針指向被刪除結點的前驅結點
			laterNode.setPrevious(previousNode);
		currentNode = null;
		}
	
		return headNode;
	}

2.循環鏈表
在單向鏈表和雙向鏈表中,都採用NULL值表示鏈表的結束。然而,循環鏈表沒有
結束標誌。當遍歷循環鏈表時需要特別小心,否則將會無限地遍歷鏈表,因爲在循環鏈表中每個結點都有一個後繼結點。
注意:與單向鏈表不同,循環鏈表中沒有next指針爲NULL的結點。循環鏈表在某
些情況下是非常有用的。例如,當多個進程需要在相同的時間內使用同一個計算機資源(CPU)時,必須確保在所有其他進程使用這些資源完前,沒有進程訪問該資源(輪詢算法)。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章