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)时,必须确保在所有其他进程使用这些资源完前,没有进程访问该资源(轮询算法)。
转载:https://blog.csdn.net/SB_Hunter/article/details/104545589