閱讀519 返回首頁    go 技術社區[雲棲]


數據結構之鏈表

數組的兩大缺點:

1。若改變數組的大小就要創建一個新的數組,並需要從原數組複製所有的數據到新的數組

2。數組元素在內存中依次順序存儲,這意味著向數組插入一項要移動數組中的其他元素

因此,我們使用鏈式結構,鏈式結構是存儲數據的結點以及指向其他節點的指針的集合。如此一來,節點可以位於內存的任意位置,而且從一個節點到另一個節點的傳遞可以通過在結構中存儲節點間引用來實現。

一。單向鏈表

1。鏈表:

如果一個節點包含指向另一個節點的數據值,那麼多個節點可以連接成一串,隻通過一個變量訪問整個節點序列,這樣的節點序列稱為鏈表(linked list)

2。單向鏈表:

如果每個節點僅包含其指向後繼節點的引用,這樣的鏈表稱為單向鏈表。

一個整型單向鏈表的實現:

 

None.gifpackage  com.sohu.blog.denns_zane.list;
None.gif
ExpandedBlockStart.gifContractedBlock.gif
/** */ /**
InBlock.gif * 
@author  dennis
InBlock.gif * @Description 整型單向鏈表節點
ExpandedBlockEnd.gif 
*/

ExpandedBlockStart.gifContractedBlock.gif
public   class  IntSLLNode  dot.gif {
InBlock.gif    
public   int  info;  //  用戶信息
InBlock.gif

InBlock.gif    
public  IntSLLNode next;  //  下一個節點,自引用
InBlock.gif

ExpandedSubBlockStart.gifContractedSubBlock.gif    
/** */ /**
InBlock.gif     * 
@param  info
InBlock.gif     * 
@param  next
ExpandedSubBlockEnd.gif     
*/

ExpandedSubBlockStart.gifContractedSubBlock.gif    
public  IntSLLNode( int  info, IntSLLNode next)  dot.gif {
InBlock.gif        
this .info  =  info;
InBlock.gif        
this .next  =  next;
ExpandedSubBlockEnd.gif    }

InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif    
/** */ /**
InBlock.gif     * 
@param  info
ExpandedSubBlockEnd.gif     
*/

ExpandedSubBlockStart.gifContractedSubBlock.gif    
public  IntSLLNode( int  info)  dot.gif {
InBlock.gif        
this (info,  null );
ExpandedSubBlockEnd.gif    }

InBlock.gif
ExpandedBlockEnd.gif}

None.gif
ExpandedBlockStart.gifContractedBlock.gif
/** */ /**
InBlock.gif * 
ExpandedBlockEnd.gif 
*/

None.gif
package  com.sohu.blog.denns_zane.list;
None.gif
ExpandedBlockStart.gifContractedBlock.gif
/** */ /**
InBlock.gif * 
@author  dennis
InBlock.gif * desc: 整型單向鏈表
ExpandedBlockEnd.gif 
*/

ExpandedBlockStart.gifContractedBlock.gif
public   class  IntSLList  dot.gif {
InBlock.gif    
protected  IntSLLNode head, tail;
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif    
public  IntSLList()  dot.gif {
InBlock.gif        head 
=  tail  =   null ;
ExpandedSubBlockEnd.gif    }

InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif    
public   boolean  isEmpty()  dot.gif {
InBlock.gif        
return  head  ==   null ;
ExpandedSubBlockEnd.gif    }

InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif    
/** */ /**
InBlock.gif     * @description 增加新節點,並設置它的next為原head
InBlock.gif     * 
@param  el
ExpandedSubBlockEnd.gif     
*/

ExpandedSubBlockStart.gifContractedSubBlock.gif    
public   void  addToHead( int  el)  dot.gif {
InBlock.gif        head 
=   new  IntSLLNode(el, head);
InBlock.gif        
if  (tail  ==   null )
InBlock.gif            tail 
=  head;
ExpandedSubBlockEnd.gif    }

InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif    
/** */ /**
InBlock.gif     * @description 增加新節點,並設置原tail的next為新節點
InBlock.gif     * 
@param  el
ExpandedSubBlockEnd.gif     
*/

ExpandedSubBlockStart.gifContractedSubBlock.gif    
public   void  addToTail( int  el)  dot.gif {
ExpandedSubBlockStart.gifContractedSubBlock.gif        
if  ( ! isEmpty())  dot.gif {
InBlock.gif            tail.next 
=   new  IntSLLNode(el);
InBlock.gif            tail 
=  tail.next;
ExpandedSubBlockStart.gifContractedSubBlock.gif        }
  else   dot.gif {
InBlock.gif            head 
=  tail  =   new  IntSLLNode(el);
ExpandedSubBlockEnd.gif        }

ExpandedSubBlockEnd.gif    }

InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif    
public   int  deleteFromHead()  dot.gif {
InBlock.gif        
if  (head  ==   null )
InBlock.gif            
throw   new  NullPointerException();
InBlock.gif        
int  el  =  head.info;
InBlock.gif        
if  (head  ==  tail)
InBlock.gif            head 
=  tail  =   null ;
InBlock.gif        
else
InBlock.gif            head 
=  head.next;
InBlock.gif        
return  el;
ExpandedSubBlockEnd.gif    }

InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif    
public   int  deleteFromTail()  dot.gif {
InBlock.gif        
if  (head  ==   null )
InBlock.gif            
throw   new  NullPointerException();
InBlock.gif        
int  el  =  tail.info;
InBlock.gif        
if  (head  ==  tail)
InBlock.gif            head 
=  tail  =   null ;
ExpandedSubBlockStart.gifContractedSubBlock.gif        
else   dot.gif {
InBlock.gif            IntSLLNode temp;
InBlock.gif            
for  (temp  =  head; temp.next  !=   null   &&  temp.next  !=  tail; temp  =  temp.next)
InBlock.gif                tail 
=  temp;
InBlock.gif            System.out.println(tail.info);
InBlock.gif            tail.next 
=   null ;
ExpandedSubBlockEnd.gif        }

InBlock.gif        
return  el;
InBlock.gif
ExpandedSubBlockEnd.gif    }

InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif    
public   void  printAll()  dot.gif {
InBlock.gif        
for  (IntSLLNode temp  =  head; temp  !=   null ; temp  =  temp.next)
InBlock.gif            System.out.print(temp.info 
+   "   " );
ExpandedSubBlockEnd.gif    }

InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif    
public   boolean  isInList( int  el)  dot.gif {
ExpandedSubBlockStart.gifContractedSubBlock.gif        
for  (IntSLLNode temp  =  head; temp  !=   null ; temp  =  temp.next)  dot.gif {
InBlock.gif            
if  (temp.info  ==  el)
InBlock.gif                
return   true ;
ExpandedSubBlockEnd.gif        }

InBlock.gif        
return   false ;
InBlock.gif
ExpandedSubBlockEnd.gif    }

InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif    
/** */ /**
InBlock.gif     * 
@param  el
ExpandedSubBlockEnd.gif     
*/

ExpandedSubBlockStart.gifContractedSubBlock.gif    
public   void  delete( int  el)  dot.gif {
ExpandedSubBlockStart.gifContractedSubBlock.gif        
if  ( ! isEmpty())  dot.gif {
InBlock.gif            
if  (head  ==  tail  &&  head.info  ==  el)
InBlock.gif                head 
=  tail  =   null ;
InBlock.gif            
else   if  (head.info  ==  el)
InBlock.gif                head 
=  head.next;
ExpandedSubBlockStart.gifContractedSubBlock.gif            
else   dot.gif {
InBlock.gif                IntSLLNode pred, temp;
//  pred為找的節點的前一節點,temp即為找到的節點
ExpandedSubBlockStart.gifContractedSubBlock.gif
                 for  (pred  =  head, temp  =  head.next; temp  !=   null ; pred  =  pred.next, temp  =  temp.next)  dot.gif {
ExpandedSubBlockStart.gifContractedSubBlock.gif                    
if  (temp.info  ==  el)  dot.gif {
InBlock.gif                        pred.next 
=  temp.next;  //  前一節點的next設置為當前節點的next
InBlock.gif
                         if  (temp  ==  tail)
InBlock.gif                            tail 
=  pred;
ExpandedSubBlockEnd.gif                    }

ExpandedSubBlockEnd.gif                }

ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif        }

ExpandedSubBlockEnd.gif    }

ExpandedBlockEnd.gif}

None.gif
None.gif

二。雙向鏈表

單向鏈表的deleteFromTail()方法指出了單向鏈表的固有問題,這種鏈表的節點僅僅包含指向後繼節點的引用,所以無法立即訪問它的前驅節點,不得不掃描整個鏈表來查找此前驅節點。因此,我們重新定義鏈表節點,包含兩個引用,一個指向前驅節點,一個指向後驅節點,也就是——雙向鏈表。
一個整型雙向鏈表的實現:
ExpandedBlockStart.gifContractedBlock.gif/** *//**
InBlock.gif * 
ExpandedBlockEnd.gif 
*/

None.gif
package com.sohu.blog.denns_zane.list;
None.gif
ExpandedBlockStart.gifContractedBlock.gif
/** *//**
InBlock.gif * 
@author dennis desc:雙向鏈表節點
ExpandedBlockEnd.gif 
*/

ExpandedBlockStart.gifContractedBlock.gif
public class IntDLLNode dot.gif{
InBlock.gif    
public int info;
InBlock.gif
InBlock.gif    
public IntDLLNode prev, next;
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif    
/** *//**
InBlock.gif     * 
@param info
InBlock.gif     * 
@param prev
InBlock.gif     * 
@param next
ExpandedSubBlockEnd.gif     
*/

ExpandedSubBlockStart.gifContractedSubBlock.gif    
public IntDLLNode(int info, IntDLLNode next, IntDLLNode prev) dot.gif{
InBlock.gif        
super();
InBlock.gif        
this.info = info;
InBlock.gif        
this.prev = prev;
InBlock.gif        
this.next = next;
ExpandedSubBlockEnd.gif    }

InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif    
public IntDLLNode(int info) dot.gif{
InBlock.gif        
this(info, nullnull);
ExpandedSubBlockEnd.gif    }

InBlock.gif
ExpandedBlockEnd.gif}

None.gif
ExpandedBlockStart.gifContractedBlock.gif
/** *//**
InBlock.gif * 
ExpandedBlockEnd.gif 
*/

None.gif
package com.sohu.blog.denns_zane.list;
None.gif
ExpandedBlockStart.gifContractedBlock.gif
/** *//**
InBlock.gif * 
@author dennis
InBlock.gif * 
ExpandedBlockEnd.gif 
*/

ExpandedBlockStart.gifContractedBlock.gif
public class IntDLList dot.gif{
InBlock.gif    
private IntDLLNode head, tail;
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif    
public IntDLList() dot.gif{
InBlock.gif        head 
= tail = null;
ExpandedSubBlockEnd.gif    }

InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif    
public boolean isEmpty() dot.gif{
InBlock.gif        
return head == null;
ExpandedSubBlockEnd.gif    }

InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif    
public void addToHead(int el) dot.gif{
InBlock.gif        
if (head == null)
InBlock.gif            head 
= new IntDLLNode(el);
ExpandedSubBlockStart.gifContractedSubBlock.gif        
else dot.gif{
InBlock.gif            head 
= new IntDLLNode(el, head, null);
InBlock.gif            head.next.prev 
= head;
ExpandedSubBlockEnd.gif        }

InBlock.gif        
if (tail == null)
InBlock.gif            tail 
= head;
InBlock.gif
ExpandedSubBlockEnd.gif    }

InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif    
public void addToTail(int el) dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif        
if (!isEmpty()) dot.gif{
InBlock.gif            tail 
= new IntDLLNode(el, null, tail);
InBlock.gif            tail.prev.next 
= tail;
ExpandedSubBlockEnd.gif        }
 else
InBlock.gif            head 
= tail = new IntDLLNode(el);
ExpandedSubBlockEnd.gif    }

InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif    
public int removeFromTail() dot.gif{
InBlock.gif        
if (head == null)
InBlock.gif            
throw new NullPointerException();
InBlock.gif        
int el = tail.info;
InBlock.gif        
if (head == tail)
InBlock.gif            head 
= tail = null;
ExpandedSubBlockStart.gifContractedSubBlock.gif        
else dot.gif{
InBlock.gif            tail 
= tail.prev;
InBlock.gif            tail.next 
= null;
ExpandedSubBlockEnd.gif        }

InBlock.gif        
return el;
InBlock.gif
ExpandedSubBlockEnd.gif    }

InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif    
public int removeFromHead() dot.gif{
InBlock.gif        
if (head == null)
InBlock.gif            
throw new NullPointerException();
InBlock.gif        
int el = head.info;
InBlock.gif        
if (head == tail)
InBlock.gif            head 
= tail = null;
ExpandedSubBlockStart.gifContractedSubBlock.gif        
else dot.gif{
InBlock.gif            head 
= head.next;
InBlock.gif            head.prev 
= null;
ExpandedSubBlockEnd.gif        }

InBlock.gif        
return el;
ExpandedSubBlockEnd.gif    }

InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif    
public boolean isInList(int el) dot.gif{
InBlock.gif        
if (head == null)
InBlock.gif            
return false;
InBlock.gif        IntDLLNode temp;
ExpandedSubBlockStart.gifContractedSubBlock.gif        
for (temp = head; temp != null; temp = temp.next) dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif            
if (temp.info == el) dot.gif{
InBlock.gif                
return true;
ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif        }

InBlock.gif        
return false;
ExpandedSubBlockEnd.gif    }

InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif    
public void delete(int el) dot.gif{
InBlock.gif        
if (head == null)
InBlock.gif            
throw new NullPointerException();
InBlock.gif        IntDLLNode temp;
ExpandedSubBlockStart.gifContractedSubBlock.gif        
for (temp = head; temp != null; temp = temp.next) dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif            
if (temp.info == el) dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif                
if (temp == head) dot.gif{
InBlock.gif                    head.next.prev 
= null;
InBlock.gif                    head 
= head.next;
ExpandedSubBlockEnd.gif                }
 else
InBlock.gif                    temp.prev.next 
= temp.next;
ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif        }

ExpandedSubBlockEnd.gif    }

InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif    
public void printAll() dot.gif{
InBlock.gif        IntDLLNode temp;
最後更新:2017-05-17 11:34:41

  上一篇:go  大數據浪潮下,前端工程師眼中的完整數據鏈圖
  下一篇:go  C#的using語句