2.[数据结构和算法分析笔记]链

本文详细介绍了链表的基本概念,包括单链表、双端链表、双向链表等不同类型的链表及其操作方法,如插入、删除等,并探讨了有序链表和双向链表的特点与效率。

1.链表

164759769.png

一个链结点是某个类的对象,这个类叫做Link。每个Link对象中都包含一个对下一个链结点引用的字段(叫做next)


1
2
3
4
5
public  class  Link {
     public  int  iData;
     public  double  dData;
     public  Link next;
}


它包含了一些数据和下一个链结点的引用。

通常,用一个包含这些数据的类的对象来代替这些数据项。


1
2
3
4
public  class  Link {
     public  inventoryItem iI;
     public  Link next;
}


引用和基本类型

类型为Link的next字段仅仅是对另一个Link对象的“引用”,而不是一个对象。Link对象并没有真正包含另一个Link对象。

1
Link someLink =  new  Link();

somelink字段没有真正的一个对象,它是一个引用。

1
Link aLink = someLink;

164925178.png

2.单链表

1
2
3
public  class  LinkList {
     private  Link first;
}


Link first表示指向链表中的第一个链结点。

在链表头出入一个数据项

165006502.png

为了插入新链结点,只需要使新创建的链结点的next字段指向原来的first,然后改变first,使它指向新创建的链结点。


1
2
3
4
5
public  void  insertFirst() {
     Link newLink =  new  Link();
     newLink.next = first; // newLink > old first
     first = newLink; // first > newLink
}


在链表头删除一个数据项

165130141.png

通过把first指向第二个链接点,断开和第一个连接点的连接。


1
2
3
4
5
public  Link deleteFirst() {
     Link temp = first;
     first = first.next; // delete it:firts > old next
     return  temp; // return deleted link
}


遍历链表显示它的内容

165216573.png

从first开始,沿着引用链从一个链结点到下一个连接点。变量current按顺序指向每一个链结点。


1
2
3
4
5
6
7
public  void  display() {
     Link current = first;
     while  (current !=  null ) {
         current = current.next;
         System.out.println(current.iI);
     }
}

3.双端链表

165256695.png

双端链表增加了对最后一个链结点的引用。双端链表类叫做FirstLastList,它由两个项,first和last,一个指向链表中的第一个链结点,另一个指向最后一个链结点。如果链表只有一个链结点,first和last都指向它,如果没有连接点,两者都为null。

双向链表很形象个U。

165316657.png

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public  class  FirstLastList {
     private  Link first;
     private  Link last;
     public  void  insertFirst() {
         Link newLink =  new  Link();
         if  (first ==  null )
             last = newLink;
         newLink.next = first;
         first = newLink;
     }
     public  void  insertLast() {
         Link newLink =  new  Link();
         if  (first ==  null )
             first = newLink;
         else
             last.next = newLink;
         last = newLink;
     }
}


链表的效率

在表头插入和删除速度很快快,时间复杂度O(1)。

4.有序链表

有序链表:数据是按照关键值有序排序的。

有序链表优于有序数组的地方是插入速度(因为元素不需要移动),另外链表可以扩展到全部有效地使用内存。

有序链表是优先级队列和堆的常用实现方法。

在有序链表中插入一个数据项

为了在一个有序链表中插入数据项,算法必须首先搜索链表,找到合适的位置:它恰好在第一个比它大的数据想的前面。


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public  class  SortedList {
     private  Link first;
     public  void  insert( long  key) {
         Link newLink =  new  Link();
         Link previous =  null ;
         Link current = first;
         while  (current !=  null  && key > current.dData) {
             previous = current;
             current = current.next;
         }
         if  (previous ==  null )
             first = newLink;
         else
             previous.next = current;
     }
}


有序链表的效率

在有序链表插入和删除某一项最多需要O(N)次比较。

5.双向链表

165425769.png

双向链表即允许向前遍历,也允许向后遍历整个链表。每个链结点都有两个指向其他连接点的引用,一个指向下一个链结点,另一个指向前一个链结点。


1
2
3
4
5
public  class  Link {
     public  double  dData;
     public  Link next;
     public  Link previous;
}


双向链表的缺点是每次插入或删除一个链结点的时候,都要处理四个链结点的引用。双向链表不必是双端链表。


1
2
3
4
class  doublyLinked {
     private  Link first;
     private  Link last;
}


Link first表示指向链表中的第一个链结点。对first的操作就是对链表第一个连接点的操作,因为他们都指向同一个对象。

Link last表示指向链表中的最后一个链结点。

插入

165514721.png

1
2
3
4
5
6
7
8
9
public  void  insertFirst() {
     Link newLink =  new  Link();
     if (first ==  null )
         last = newLink;
     else
         first.previous = newLink;
     newLink.next = first;
     first = newLink;
}


insertFirst方法把原来first指向的链结点的previous字段指向新链结点,并把新链结点的next字段指向前者。最后把first指向新连接点。


1
2
3
4
5
6
7
8
9
10
public  void  insertLast() {
     Link newLink =  new  Link();
     if (first ==  null )
         first = newLink;
     else  {
         last.next = newLink;
         newLink.previous = last;
     }
     last = newLink;
}



删除

165602127.png


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public  Link deleteFirst() {
         Link temp = first;
         if (first.next ==  null )
             last =  null ;
         else
             first.next.previous =  null ;
         first = first.next;
         return  temp;
     }
       
     public  Link deleteLast() {
         Link temp = last;
         if (first.next ==  null )
             first =  null ;
         else
             last.previous.next =  null ;
         last = last.previous;
         return  temp;
}









本文转自 LinkedKeeper 51CTO博客,原文链接:http://blog.51cto.com/sauron/1225186,如需转载请自行联系原作者
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值