数据结构与算法经典问题解析-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)时,必须确保在所有其他进程使用这些资源完前,没有进程访问该资源(轮询算法)。

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