双向链表

  1. 双向链表的图示

    2. 操作图示

  • 双向链表头插法:

  • 双向链表尾插法:

  • 双向链表插入:在某个节点后面插入新的节点

 

  • 双向链表删除:头部删除方法

 

 

  • 双向链表删除:尾部删除

  • 双向链表删除:删除某个特定节点

 

 3 ADT

3.1双向链表节点的声明

class Link{
    public long dData;
    public Link right;//指向下一个节点
    public Link left;//指向上一个节点
    ...
}

3.2 双向链表所包含的方法

    1)遍历(前向遍历,后向遍历)
      6.1.1
          displayForward();
          displayBackward();//从表尾开始 通过每个元素的previous域 一步步向前到达表头
     2)插入
             insertFirst();//在表头插入 O[1]
             insertLast();//在表尾插入  O[1]
             insertAfter();//在某一个特定元素后面插入 O[N]
     3)删除
           delteFirst();//O[1]
              deleteLast();//O[1]
              deleteKey();//O[N]

4 代码

4.1  双向链表的节点

public class DoubleLinkNode {
    public int iData;//data
    public double dData;//data
    public DoubleLinkNode next; //reference to next link
    public DoubleLinkNode pre;//reference to the previous link
    
    //constructor
    public DoubleLinkNode(int id,double dd){
        iData = id;
        dData = dd;
    }
    public void displayLink(){
        //display itself
        System.out.println
        ("iData  :  "+iData+"    dData:"+dData);
    }
}//end class DoubleLinkNode

4.2 双向链表

public class DoubleLinkList {
    private static DoubleLinkNode first;
    private static DoubleLinkNode last;
    //ref to first link on list
    public void LinkList(){
        first = null;
        last = first;
        // constructor : no items on list yet
    }
    public boolean isEmpty(){
        return first==null;
    }
    //前向遍历
    public void displayForward(){
        System.out.println(" DoubleLinkList (first-->last): ");
        DoubleLinkNode current = first;
        while (current!=null){
            current.displayLink();
            current=current.next;
        }
        System.out.println("");
    }
    //后向遍历
    public void displayBackward(){
        System.out.println(" DoubleLinkList (first-->last): ");
        DoubleLinkNode current = last;
        while (last!=null){
            current.displayLink();
            current=current.pre;
        }
        System.out.println("");
    }
    //查找结点
    public DoubleLinkNode findNode(DoubleLinkNode node){
        DoubleLinkNode current = first;
         while (current!=null){
        //     current.displayLink();
             if(current.dData ==node.dData && current.iData ==node.iData ){
                 return current;
             }
            current = current.next;
         }
        return null;
    }
    //表头插入
    public void insertFirst(DoubleLinkNode node){
        if( isEmpty()){ 
            first = node;
            last = node;
            return;
        } 
        node.next=first;
        first.pre = node;
        first =node;
    }
    //表尾插入
    public void insertLast(DoubleLinkNode node){
        if( isEmpty()){ 
            first = node;
            last = node;
            return;
        } 
        node.next = null;
        node.pre = last;
        last.next = node;
        last = node;
    }
    //删除 表头删除
    public DoubleLinkNode deleteFrist(){
        DoubleLinkNode temp = first;
        if( !isEmpty()){
            first.pre = null;
            first= first.next;
        }
        return temp;
    }
    // 删除 表尾删除
    public DoubleLinkNode deleteLast(){
        DoubleLinkNode temp = first;
        if( !isEmpty()){
            last= last.pre;
            last.next = null;
        }
        return temp;
    }
    //删除指定元素
    public DoubleLinkNode deleteKey(DoubleLinkNode node){
        //找到该指定元素
        DoubleLinkNode current = first;
        DoubleLinkNode pre = null;
         while (current!=null){
        //     current.displayLink();
             if(current.dData ==node.dData && current.iData ==node.iData ){
                 //just find the key that need be deleted
                 pre.next = current.next;
                 current.next = pre;
                 return current;
             }
             pre = current;
            current = current.next;
         }
        return null;
        
    }
    
    
    //特定节点后面插入 node1 某个节点 node 2 待插入的节点
    public boolean insertAfter(DoubleLinkNode node1,DoubleLinkNode newNode){
        //find the specail node
        DoubleLinkNode current = first;
        DoubleLinkNode pre = null;
         while (current!=null){
        //     current.displayLink();
             if(current.dData ==node1.dData && current.iData ==node1.iData ){
                 pre=current;
                 current = current.next;
                break;
             }
             pre=current;
            current = current.next;
         }
        if(current!=null){
            newNode.next = current;
            current.pre = newNode;
            newNode.pre = pre;
            pre.next = newNode;
            return true;
                    
        }
         return false;
    }
}

5 双向链表应用 ===>双端队列

作为双端队列的基础.在双端队列中,可以从任何一头插入和删除,双向链表提供了这个能力.

5.1 双端队列基本操作

insertLeft();
insertRight();
removeLeft();
removeRight();
isEmpty();
display();

5.2 代码

public class Dqueue {
    //双端链表
    private DoubleLinkList list;
    public Dqueue(){
        this.list = new DoubleLinkList();
    }
    //insert from the front direction
    public void insertLeft(DoubleLinkNode node)    {
        list.insertFirst(node);
    }
    //insert from the back direction
    public void insertRight(DoubleLinkNode node) {
        list.insertLast(node);
    }    
    //delete from the front direction
    public DoubleLinkNode removeLeft() {
        return list.deleteFrist();
    }   
    //delete from the back direction
    public DoubleLinkNode removeRight(){
        return list.deleteLast();
    }                  
    public boolean isEmpty(){return list.isEmpty();}                         
    public void display()   {list.displayForward();}                  
}
public class DqueueApp {
    private static Dqueue que=new Dqueue();
    //constructor
    public DqueueApp(){
        que = new Dqueue();
    } 
    public static void main(String[] args) {  
        que.insertLeft(new DoubleLinkNode(1,1.1));
        que.insertLeft(new DoubleLinkNode(3,3.3));
        que.insertLeft(new DoubleLinkNode(2,2.2));
        que.display();
    }
}

6 总结

6.1 双向链表 VS 单链表

1 单链表缺陷:
沿链表的反向遍历困难。
链表正向遍历:current = current.next;

2 双向链表优势:
允许向前遍历,也允许向后遍历整个链表。

6.2 双向链表的缺陷

每插入或者删除一个链结点时候,要处理四个链结点的引用(单链表处理两个)
两个连接前一个节点,两个连接后一个节点。
链结点占用空间也大一点(多了两个引用)

6.3 双向链表 VS 双端链表

双端链表:保持一个对链表最后一个元素的引用
双向链表不必是双端链表,但这种方式是有用的(可以进行队尾删除)。

 

 

 

 

 

posted @ 2013-06-24 20:19  王超_cc  阅读(326)  评论(0编辑  收藏  举报