2018.8.10
這道題用非遞歸方法需要3個指針做,一個指向後一個結點(later),一個指向中間結點(temp),一個指向前一個結點(front)。每次反轉前front記錄下一結點位置,temp與later進行反轉(此時temp與front之間的指針會斷開),然後later前移至temp位置,temp前移至front位置。循環進行之後的反轉。反轉結束後將最後兩個結點反向,並去掉最開始兩個結點的自循環。
代碼實現過程的注意點:1.輸入head==null,2.輸入鏈表只有一個結點,3.最後兩個結點忘記操作,4.頭兩個結點未去除自循環
另外還有一種遞歸思路可以從鏈表尾部不斷向前翻轉,以此解決鏈表不能回溯的缺點。
鏈表反轉題還有一道升級版,要求每隔k個元素進行一次反轉,比這個要複雜得多。很早之前做過,可以參考之前的文章:
#數據結構與算法學習筆記#PTA6:鏈表翻轉升級版(C/C++)
題目描述
輸入一個鏈表,反轉鏈表後,輸出新鏈表的表頭。
Java實現代碼:
/**
*
* @author ChopinXBP
* 輸入一個鏈表,反轉鏈表後,輸出新鏈表的表頭。
*
*
*/
public class ReverseList_15 {
public static class ListNode {
int val;
ListNode next = null;
ListNode(int val) {
this.val = val;
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
ListNode head = new ListNode(0);
ListNode p = head;
for (int i = 0; i < 5; i++) {
ListNode newnode = new ListNode(i + 1);
p.next = newnode;
p = p.next;
}
p = head;
System.out.print("原序列: ");
for (int i = 0; i < 6; i++) {
System.out.print(p.val);
p = p.next;
}
p = Solution(head);
System.out.print("\n翻轉序列: ");
for (int i = 0; i < 6; i++) {
System.out.print(p.val);
p = p.next;
}
}
public static ListNode Solution(ListNode head) {
if (head == null)
return null;
else if (head.next == null)
return head;
ListNode temp = head.next; //指向前一個結點
ListNode later = head; //指向後一個結點
//每次循環先定義一個former指向下一個結點,將temp與later所指結點反向,並依次前進later與temp
while (temp.next != null) {
ListNode former = temp.next; //指向下一個結點
temp.next = later;
later = temp;
temp = former;
}
temp.next = later; //將最後兩個結點反向
head.next = null; //去掉頭兩個結點的自循環
return temp;
}
}
C++實現示例:
//第一種方法是:非遞歸方法
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) :
val(x), next(NULL) {
}
};
class Solution {
public:
ListNode* ReverseList(ListNode* pHead) {
if(pHead==NULL) return NULL;//注意程序魯棒性
ListNode* pNode=pHead;//當前指針
ListNode* pReverseHead=NULL;//新鏈表的頭指針
ListNode* pPrev=NULL;//當前指針的前一個結點
while(pNode!=NULL){//當前結點不爲空時才執行
ListNode* pNext=pNode->next;//鏈斷開之前一定要保存斷開位置後邊的結點
if(pNext==NULL)//當pNext爲空時,說明當前結點爲尾節點
pReverseHead=pNode;
pNode->next=pPrev;//指針反轉
pPrev=pNode;
pNode=pNext;
}
return pReverseHead;
}
}
//第二種方法是:遞歸方法
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) :
val(x), next(NULL) {
}
};
class Solution {
public:
ListNode* ReverseList(ListNode* pHead) {
//如果鏈表爲空或者鏈表中只有一個元素
if(pHead==NULL||pHead->next==NULL) return pHead;
//先反轉後面的鏈表,走到鏈表的末端結點
ListNode* pReverseNode=ReverseList(pHead->next);
//再將當前節點設置爲後面節點的後續節點
pHead->next->next=pHead;
pHead->next=NULL;
return pReverseNode;
}
};
測試代碼:
// ====================測試代碼====================
ListNode* Test(ListNode* pHead)
{
printf("The original list is: \n");
PrintList(pHead);
ListNode* pReversedHead = ReverseList(pHead);
printf("The reversed list is: \n");
PrintList(pReversedHead);
return pReversedHead;
}
// 輸入的鏈表有多個結點
void Test1()
{
ListNode* pNode1 = CreateListNode(1);
ListNode* pNode2 = CreateListNode(2);
ListNode* pNode3 = CreateListNode(3);
ListNode* pNode4 = CreateListNode(4);
ListNode* pNode5 = CreateListNode(5);
ConnectListNodes(pNode1, pNode2);
ConnectListNodes(pNode2, pNode3);
ConnectListNodes(pNode3, pNode4);
ConnectListNodes(pNode4, pNode5);
ListNode* pReversedHead = Test(pNode1);
DestroyList(pReversedHead);
}
// 輸入的鏈表只有一個結點
void Test2()
{
ListNode* pNode1 = CreateListNode(1);
ListNode* pReversedHead = Test(pNode1);
DestroyList(pReversedHead);
}
// 輸入空鏈表
void Test3()
{
Test(NULL);
}
int _tmain(int argc, _TCHAR* argv[])
{
Test1();
Test2();
Test3();
return 0;
}
#Coding一小時,Copying一秒鐘。留個言點個讚唄,謝謝你#