這個問題有兩種解法。
第一種,我取名叫尾刪頭插法:
核心思路:將每一次oldhead後面的tmp節點刪除,並將該節點頭插,依次循環。直到oldhead變成鏈表的尾部,即tmp爲空,循環結束。
如下圖單鏈表:oldhead爲逆序前原單鏈表的頭,head爲每逆置一次的單鏈表的新頭,tmp爲每一次要被刪除的節點。過程1表尾刪,過程2表示頭插。
方法代碼:
void SListReverse1(SListNode **pphead)
{
//這裏我是通過二級指針**pphead來訪問的頭部,還可以通過將頭部封裝成一個結構體直接訪問。
SListNode *head = *pphead;//每次循環中始終指向當前鏈表的頭
SListNode *tmp = head->next;//每次循環中始終指向被刪的節點
SListNode *oldhead = *pphead;//每次循環中始終指向被刪的前一個節點
while (tmp)//tmp爲空,代表逆序結束
{
oldhead->next = tmp->next;//架空tmp(後刪)的一部分
tmp->next = head;//讓tmp變成新頭(頭插)
head = tmp;//換頭
tmp = oldhead->next;//讓tmp變成下一次循環中待刪除的節點
}
*pphead = head;
}
第二種,我取名叫依次改指向法:
核心思路:找到原頭部後面的每一個節點,依次讓它指向每一次新的頭部。
如下圖:pre爲每一次變換後鏈表的頭部,cur爲需要變換指向的節點,next爲該節點等候一個節點,便於找到下一次需要變換的目標節點。
方法代碼:
void SListReverse2(SListNode **pphead)
{
SListNode *pre = *pphead;
SListNode *cur= pre->next;//被執行操作的節點
SListNode *next = cur;//被執行操作的後一個節點,暫時指在cur,在循環開始的時候跳轉到其後一個節點
pre->next = NULL;//此時的頭,將會成爲尾,所以要設置尾節點
while (next)
{
next = next->next;//放前面避免next爲空。
cur->next = pre;//改變箭頭方向
pre = cur;//循環節點依次後移
cur = next;
}
*pphead = pre;//循環跳出時,cur和next都指向空,此時的頭爲pre
}
總結
1.不能忘記將新頭賦給*pphead。
2.要注意兩種方法結束循環時的判定條件。
最後再給出我的單鏈表的節點結構體定義:
typedef struct SListNode
{
SLTDataType data;
struct SListNode *next;
}SListNode;