1. 程式人生 > >逆轉交替合並兩個鏈表

逆轉交替合並兩個鏈表

包含 con 技術分享 article 進行 log 輸入 帶來 方式

一、問題描寫敘述

鏈表A和B

A: 1->2->3->4

B: a->b->c->d

請逆轉交替合並兩個鏈表,演示樣例結果例如以下:

4->d->3->c->2->b->1->a

節點類型定義例如以下:

classNode {

public Node next;

...

}


二、源碼:

傳入兩個A和B鏈表,返回處理後的鏈表:

Node reverse_merge(Node A, Node B) 
{
	//A、B都僅僅有一個節點
	if(A.next==null)
	{
		A.next=B;
		return A;
	}
	//A、B都大於等於2個節點
	Node nextA;
	Node nextB;
		
	nextB = B.next;
	B.next = null;
	nextA = A.next;
	A.next = B;
	B = nextB;
	while (nextA.next != null)
        {
		B.next = A;
		A = nextA;
		nextA = A.next;
		A.next = B;
		B = nextB;
	}
	nextB.next = A;
	nextA.next = B;
	return nextA;
}



三、解析:

程序分成三個部分——while循環之前、while循環體、while循環之後。

1)處理之前的鏈表A和B

技術分享

2)while循環——核心的處理部分

這裏處理程序的可反復的部分。我們的目標是紅色的部分,要達成紅色的鏈接模式,有兩個原子結構:深紅色圓圈1和藍色圓圈2

技術分享

可是1中須要特別處理a所在的節點。僅對於a所在的節點須要一個next=null的操作,也就是說1中的第一個原子要放在循環之外實現。這包含1指向a。b指向1的操作。

換種方式。假設使用2方式,就僅僅須要將1指向a放在循環之外。

所以,這裏採用了2中描寫敘述的原子結構。


原子結構須要的信息

當我們進行到某一次循環時。如果進行到藍色圓圈的操作了。這時候我們鏈表的狀態為:

技術分享

更為直觀的畫法為:

技術分享

它涉及到3個節點——2,3和c。

當中紅色部分是我們希望做到的鏈接方式。

為了鏈接c->2,3->c。必須知道有對應的指針記錄他們的位置。

所以在循環之前我們須要掌握這三個元素的地址。而且在處理完之後,用同樣的方式表示下一次須要處理的原子結構。

比例如以下面這樣的方式記錄這次循環中設計的3個節點的地址:

技術分享

A、nA、B代表指向對應節點的指針或者說是引用。

在處理完畢之後須要用同樣的方式記錄下一次原子結構涉及的節點,這樣才幹保證循環可以按統一邏輯運行下去,我們的目標是:

技術分享

這些賦值操作正是循環體的中代碼所做的事情。恰好代碼也是依照上面指定的命名形式,有一點差別。圖中的nA代表代碼中的nextA。除此之外。代碼中定義了nextB作為一個中間變量,用來記錄c->d斷開之前d節點的地址。由於c指向2之後就會失去對d的聯系。這個中間變量是必須的。

3)while循環之前——解決預備操作所帶來的問題

我們還沒有處理a節點,由於它太特殊了,沒有合適的原子結構能包含它。所以我們把它放在循環體之外,而且為循環做好準備工作,我們希望的結果是這樣:

技術分享
在這之後我們就能夠把1,2,b放在循環體中處理。這裏也考慮了A、B都僅僅有一個節點的情況。也須要單獨處理。


4)while循環之後——最後的處理

當我們發現B鏈表到達末尾時,結束循環。但這時候並有處理末尾節點,換句話說,末尾節點不在原子結構中。我們的循環會停止在這個原子結構中:

技術分享

作為最後的操作,我們須要手動處理d->3,4->d的鏈接步驟——這也是沒有辦法的。由於原子結構的處理必須找到可以把全部指針傳遞下去的節點,作為最後的節點是沒辦法吧指針繼續傳遞下去。


這不是一個完整的方法。還有非常多事情沒有處理,比方輸入的A、B假設不等長,應該怎樣處理。

另外Node數據結構並沒有完整的定義。只是這都不是本文討論的重點。

逆轉交替合並兩個鏈表