链表基础知识

来源:互联网 发布:卖家网数据监控 编辑:程序博客网 时间:2024/06/06 18:13

1.为什么用LinkedList

         Array是一个非常有用的数据结构,但是有两个限制:(1)当改变原有array的size的时候需要将原有array的所有元素copy到新array中去(2)由于array的数据存储在内存中是连续空间,导致插入和删除都会带来其他数据的移动。

         链表是由一系列的节点组成,这些节点可以处在不从的内存位置,通过指针将这些节点连接在一起。

2.单链表

2.1只有head变量的单链表

 

单链表如图所示:

(1)节点有两个属性:data为数值;next为指向下一个节点的引用

public class Node {

    public int data;

    public Nodenext;

    public Node(int i){

       this(i,null);

    }

    public Node(int i, Node n){

       this.data = i;

       this.next = n;

    }

}

(2)add操作:在单链表的末尾添加新的节点

Node head = new Node(1);

head.next = new Node(2);

head.next.next =new Node(3);

问题:如果添加的节点很多的话,例如100,1000等,此方式行不通,因为head.next.···无数个next···.next会让人抓狂。

2.2有 head、tail变量的单链表

为了解决该问题,在单链表上加上tail的。


在末端添加新的节点为

tail.next =new Node(i);

tail = tail.next;

问题:添加了tail以后仍然有问题,如果要删除某个节点的话,则需要从头开始寻找该节点以及该节点的前一个节点,然后删除,时间复杂度为O(n)。以删除最后一个节点为例,代码如下:

public Node deleteFromTail(){

       Node tmp = head;

       Node deleteNode = null ;

       for(;tmp!=null&&tmp.next!=null&&tmp.next!=tail;tmp=tmp.next){

           if(tmp==null){

              deleteNode = null;

           }

           else if(tmp.next==null){

              deleteNode = tmp;

              head = tail = null;

             

           }

           else{

              deleteNode = tail;

              tail = tmp;

             

           }

       }

       return deleteNode;

    }

3.双链表

为了解决上面的问题,在node里添加了指向前一个节点的变量,如下图所示:


如下为从双链表从链表末尾删除节点的实现,少了单链表的轮询删除。

public Node deleteFromTail2(){

       Node deleteNode = null;

       if(!isEmpty()){

           if(head==tail){

              head=tail=null;

           }

           else{

              deleteNode=tail;

              tail = tail.pre;

              tail.next=null;     

           }

       }

       return deleteNode;

    }

4.循环链表

         场景:如果有几个程序轮流使用CPU,则会构成循环列表。


         其实用上面的单链表或双链表也可以实现,只是每次都要对current的位置进行判断:是不是到了tail的位置,如果是,则current=head重新轮回;如果不是,则current=current.next。

5.跳表(skip list)

链表的优点:插入和删除操作简单,不会像数组那样带来其他元素的位置移动。

链表的缺点:查询数据的时候很麻烦,从头开始轮询,不像数组那样通过下标就可以获得数据。

关于跳表的文章:

http://www.spongeliu.com/63.html

http://www.cnblogs.com/xuqiang/archive/2011/05/22/2053516.html

讲得都很详细。