1. 程式人生 > >演算法學習之資料結構之單鏈表反轉,兩兩反轉

演算法學習之資料結構之單鏈表反轉,兩兩反轉

  連結串列反轉,就是將連結串列從1->2->3->4->5這種形式反轉成5->4->3->2->1這種形式,目前能想到的有兩種實現方式,對於什麼是連結串列,連結串列的一些性質就不多說了,直接說兩種實現方式,實現方式如下:   1,用頭節點插入法新建連結串列。反轉連結串列,有建立連結串列的兩種方式(頭節點插入法,尾節點插入法)知道,頭結點插入法形成的連結串列是和輸入順序相反的,尾節點插入法形成的連結串列是和輸入順序相同的,所以其中一種方法是,遍歷原連結串列,然後用原連結串列的輸出元素順序用頭結點插入法新建連結串列,這樣新建的連結串列就是反轉後的連結串列。具體虛擬碼操作:
reverse(NodeList list)
if list == null
    return null
NodeList newList
Node temp = list->next
newList->next = null
while temp != null
    temp->next = newList->next
    newList->next = temp
    temp = temp->next
return newList


  2,就地反轉連結串列。遍歷連結串列,將當前連結串列的頭結點下一個的下一個節點插入到頭結點的下一個節點中,這樣就能就地反轉了。如1->2->3->4->5先轉成2->1->3->4->5,然後在轉成3->2->1->4->5這樣知道最後一個節點就可以就地反轉了。具體為程式碼操作如下:
reverse(NodeList list)
if list == null
    return null
Node temp = list->next
while temp->next != null
    Node insert = temp->next // 取出要反轉節點下一個節點
    insert->next = list->next // 將這個節點插入到頭結點後面
    list->next = insert 
    temp = temp->next // 繼續遍歷
return list

     二、兩兩反轉   兩兩反轉單項鍊表就是把每兩個數反轉一次。如:A -> B -> C ->D -> E -> F ->G -> H -> I  兩兩反轉後變為 B -> A -> D ->C -> F -> E ->H -> G -> I   我們一共需要分析四個指標,prev, current, next, nextNext。   分析:我們需要兩個“指標”指著當前要反轉的兩個值current和next。兩兩反轉後,我們還需要記錄下一個的值,即反轉A和B後, 需要記錄 C 值,我們才能夠不斷向下走,直到到達連結串列末端,所以,需要另一個指向下一個值的“指標”,即nextNext。反轉以後,A的下一個是C, 但是,實際上,A的下一個應該是D,所以,每次反轉時,我們需要更新前一個值的下一個值,也就是說把 A -> C 改成 A -> D,所以需要prev指標。所以,要完成這個操作,我們總共需要4個“指標”。具體看程式碼。
  java程式碼: 先定義資料結構:
class Node {  
    char value;  
    Node next;    
} 


具體操作:   
/**
	 * 兩兩反轉具體操作,先得到當前節點的下個節點和下下個節點,然後下個節點的指標指向當前節點nextNode.next = current,當前節點的指標只想下下個節點current.next = nextNextNode,這樣這兩個節點就互換了,然後更新前一個節點的下一個節點值previousNode.next = nextNode,在更新的時候要判斷是不是第一次,因為第一次兩兩反轉沒有前一個節點指標,指向的是null,然後賦值繼續迴圈previousNode = currentNode; currentNode = nextNextNode;這樣就可以了。。
	 * @param list 要兩兩反轉的連結串列頭結點
	 * @return 反轉後的連結串列頭結點
	 */
	public static Node reverseInPair(Node list) {
	    Node current = list;  
	    if (current == null || current.next == null){
	        return current;  
	    }  
	    Node head = current.next;// 儲存頭結點,用以返回。
	    Node previousNode = null;  // 這是指向前一個節點的指標
	      
	    while(current != null && current.next != null) {  
	        // 得到下一個節點和下一個的下一個節點
	        Node nextNode = current.next;  
	        Node nextNextNode = nextNode.next;   
	        nextNode.next = current;  
	        current.next = nextNextNode;  
	          
	        //更新前一個節點的下一個節點
	        if (previousNode != null) {  
	            previousNode.next = nextNode;  
	        }  
	        previousNode = current;  
	        current = nextNextNode;  // 當前節點賦值為下一個的下一個節點繼續遍歷
	    }  
	      
	    return head;  
	}