链表的类型
单链表,双端链表,有序链表,双向链表,有迭代器的链表(迭代器是用来随机访问链表元素的一种方法)。
单链表
链表本身是由一个个的link对象构成的。每个link对象都包含两个部分:
1,数据本身。
2,指向下一个link对象的引用。
因此链表就是很多的link对象,它们根据引用互相连接,形成了一个逻辑上的链表。而实际这些link对象在物理上并不一定是相邻的。
由此可见,每个link对象仅知道下一个link对象的位置,而无法知道其他对象的位置,比如,上一个link对象,或下个link对象后面的那个link对象。
这就意味着,如果想取出第12个数据项,必须遍历前11个数据项。
下面是java实现:
Link类是链表上的节点,LinkList是链表本身。
public class LinkList {
private Link first;
public LinkList(){
first = null; //first代表链表的第一个节点。一开始,链表为null,因此第一个节点也为空。
}
public void insertFirst(int id){
Link newLink = new Link(id); //这里的思想就是永远在链表头插入节点。
newLink.next = first; //首先把新插入的节点的next指向first,也就是之前的那个节点。第一次循环的时候,first为null。
first = newLink; //然后新插入的节点成了链表的第一个节点。由于总是在表头插入新节点,再加上链表只能单向查询,因此查出来的元素顺序总是倒叙的。
//在链表尾部插入数据可以实现,但效率低下。因为总是得顺着链表移动到尾部后,才能插入数据。
}
public void displayList(){
Link current = first;
while(current != null){ //循环的打印出每个节点。
current.displayLink();
current = current.next;
}
}
public void delete(String key){
Link current = first;
Link previous = first; //因为需要将前一个Link.next指向被删除link后面的那个link,所以需要保存previous以便于修改。
while(current.sData != key){
{
if(current.next == null){
}else{
previous = current;
current = current.next;
}
}
}
if(current == first){
first = first.next;
}else{
previous.next = current.next;
}
}
}
class Link {
public int iDate;
public Link next;
public Link(int id){
iDate = id;
}
public void displayLink(){
System.out.println("{" + iDate + "}");
}
}
双端链表
注意是双端链表而不是双向链表。双端链表和单链表唯一的区别就是,在first不仅指向链表的开头,同时也指向链表的结尾(即在LinkList类,不仅有first,而且有last)。这样,就可以方便的在链表尾部插入数据了。
这使得双端链表可以用于实现队列。因为队列总是在链表尾部插入新节点的。
但是在双端链表中,仍然不能高效的删除最后一个节点。只有双向链表才能解决这个问题。
双端链表的实现:
public class LinkList {
private Link first;
private Link last;
public LinkList(){
first = null;
last = null;
}
public void insertFirst(String s){
Link newLink = new Link(s);
if(isEmpty()){
first = newLink;
last = newLink;
}else{
newLink.next = first;
first = newLink;
}
}
public void insertLast(String s){
Link newLink = new Link(s);
if(isEmpty()){
first = newLink;
last = newLink;
}else{
last.next = newLink;
last = newLink;
}
}
public void displayLink(){
Link current = first;
while(current != null){
current.displayLink();
current = current.next;
}
}
public boolean isEmpty(){
if(first == null || last == null){
return true;
}
else{
return false;
}
}
}
双向链表
使用双向链表可以很容易的正向查询数据和反向查询数据。实现方法是每个link节点不仅有指向下一个节点的reference,也有指向上个节点的reference。
缺点就是每插入一个节点,就需要修改4个reference(不过也还能接受吧)。
链表的效率
在表头插入和删除都是O(1)。查找,删除和在制定节点插入都是O(n)。所以和数组操作一样。但是链表插入和删除都不需要移动其他节点,所以这方面比数组效率高。
有序链表
有序链表查找和删除的效率是O(n),因为在有序链表里搜索,仍然需要遍历链表。但是如果需要频繁的插入删除最小值,则有序列表非常适合。比如用来实现优先级队列。