链表结构之双端链表

双端链表:双端链表与传统链表非常相似.只是新增了一个属性-即对最后一个链结点的引用
《链表结构之双端链表》

如上图所示:由于有着对最后一个链结点的直接引用.所以双端链表比传统链表在某些方面要方便.比如在尾部插入一个链结点.双端链表可以进行直接操作

但传统链表只能通过next节点循环找到最后链结点操作.所以双端链表适合制造队列.

下面的双端链表类.有几个重要方法.

insertFirst(插入首链结点)
这个方法与上篇博文的单链表是基本一样的.唯一区别就是,多了个last引用的操作.正常由于last是指向尾链结点的引用,所以插入首链结点是与他无关的.

但当链结点为空(isEmpty())的时候,这会追加的链结点既是首链结点又是尾链结.所以需要将last指向它.
public
 
void
 insertFirst(
double
 dd) {
    Link newLink 

=
 
new
 Link(dd);
    

if
(isEmpty()){
        last 

=
 newLink;
    }
    newLink.next 

=
 first;
    first 

=
 newLink;    
}

insertLast(插入尾链结点)

插入尾部链结点也是与普通的理解基本一致,所以不多赘述.唯一也要注意的是链结点为空(isEmpty())的时候.需要将first指向该链结点.
public
 
void
 insertLast(
double
 dd) {
    Link newLink 

=
 
new
 Link(dd);
    

if
(isEmpty()) {
        first 

=
 newLink;
    }

else
 {
        last.next 

=
 newLink;
    }
    last 

=
 newLink;
}
看下插入尾部链结点的引用指向:

《链表结构之双端链表》
deleteFirst(删除首部链结点)

这个需要注意的就是,如果仅剩下一个链结点.那么删除后last就应该指向null了.
public
 
void
 deleteFirst() {
    first 

=
 first.next;
    

if
(first.next 
==
 
null
) {
        last 

=
 
null
;
    }    
}
最后这个代码如下:
《链表结构之双端链表》
《链表结构之双端链表》
FirstLastLink

package com.dbstructor.oop3;

// 链结点类
class Link {
    
public double dData;
    
public Link next;
    
public Link(double dd) {
        dData 
= dd;
    }
    
public void displayLink() {
        System.out.print(dData 
+  );
    }
}
// 双端链表类
class FirstLastList {
    
public Link first;
    
public Link last;
    
public FirstLastList() {
        first 
= null;
        last 
= null;
    }
    
public boolean isEmpty(){
        
return (first == null);
    }
    
// 表头插入
    public void insertFirst(double dd) {
        Link newLink 
= new Link(dd);
        
if(isEmpty()){
            last 
= newLink;
        }
        newLink.next 
= first;
        first 
= newLink;    
    }
    
// 表尾插入
    public void insertLast(double dd) {
        Link newLink 
= new Link(dd);
        
if(isEmpty()) {
            first 
= newLink;
        }
else {
            last.next 
= newLink;
        }
        last 
= newLink;
    }
    
// 删除表头
    public void deleteFirst() {
        first 
= first.next;
        
if(first.next == null) {
            last 
= null;
        }    
    }
    
    
public void displayList() {
        System.out.print(
List (first—>last));
        Link current 
= first;
        
while(current != null){
            current.displayLink();
            current 
= current.next;
        }
        System.out.println();
    }
}
public class FirstLastApp {
    
public static void main(String[] args) {
        FirstLastList theList 
= new FirstLastList();
        
// 插入链表头数据
        theList.insertFirst(22);
        theList.insertFirst(
44);
        theList.insertFirst(
66);
        
// 插入链表尾数据
        theList.insertLast(11);
        theList.insertLast(
33);
        theList.insertLast(
55);
        
        theList.displayList();
        
// 删除表头数据
        theList.deleteFirst();
        theList.deleteFirst();
        
        theList.displayList();
    }

}
代码运行结果为:
List (first—>last)
66
.
0
 
44
.
0
 
22
.
0
 
11
.
0
 
33
.
0
 
55
.
0
 
List (first—>last)

22
.
0
 
11
.
0
 
33
.
0
 
55
.
0
 
链表的效率

这里顺便谈下链表和数组相比效率的优越性.在表头插入和删除的速度都很快,因为只需要改变一下引用所以花费O(1)的时间.

平均起来查找,删除和在指定节点后插入数据都需要搜索一半的链结点.需要O(N)次比较和数组一样.然由于链表删除插入的时候

不需要像数组那种元素的移动.所以效率还是要优于数组.

还有一点就是链表的内存可以随时的扩展内存.而数组的内存是一开始就固定好的.这样就会导致数组的效率和可用性大大下降.

    原文作者:算法小白
    原文地址: https://www.cnblogs.com/bluedream2009/archive/2009/09/02/1558687.html
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞