1. 程式人生 > >單鏈表反轉(遞迴和非遞迴)

單鏈表反轉(遞迴和非遞迴)

單鏈表反轉有遞迴和非遞迴兩種演算法。

下面定義節點

typedef struct ListNode{
	int value;
	ListNode* next;
}ListNode;

在遞迴演算法中的做法是:

1找到最後一個節點和倒數第二個節點,把最後一個節點設為頭節點的後繼

2反轉這兩個節點

3倒數第三個和第四個節點重複執行步驟2

其中注意,連結串列是以節點後繼為NULL結束的,在更改指標的過程中要把改後的節點後繼改為NULL

程式碼如下:

void Inversion_Recursion(ListNode* p,ListNode* Head)
{
    if(NULL == p)
    {
        return;
    }
    if(p->next==NULL)
    {
        Head->next=p;
        return;//找到最後一個節點
    }
    Inversion_Recursion(p->next,Head);
    p->next->next=p;//反轉節點
    p->next=NULL;//第一個節點反轉後其後繼應該為NULL
}

非遞迴實現很簡單,只需要遍歷一遍連結串列,在遍歷過程中,把遍歷的節點一次插入到頭部。在這個過程之後,第一個節點成了最後節點,因此要特殊處理,改其後繼為NULL

void Inversion(ListNode* Head)
{
	ListNode *current,*tmp;
	current=Head->next;
	if(current!=NULL)//反轉後第一個節點的後繼要為NULL
	{
		tmp=current;
		current=current->next;
		tmp->next=NULL;
	}
	
	while(current!=NULL)
	{
		tmp=current;
		current=current->next;
		tmp->next=Head->next;
		Head->next=tmp;
	}
}

測試程式碼:
#include<iostream>
#include<malloc.h>

typedef struct ListNode{
	int value;
	ListNode* next;
}ListNode;


int main()
{
	ListNode* Head=(ListNode*)malloc(sizeof(ListNode));
	if(Head==NULL)
		std::cout<<"malloc failed"<<std::endl;
	ListNode* tmp=Head;
	for(int i=1;i<=10;i++)
	{
		tmp->next=(ListNode*)malloc(sizeof(ListNode));
		tmp->next->value=i;
		tmp->next->next=NULL;
		tmp=tmp->next;
	}
	Inversion_Recursion(Head->next,Head);
	Inversion(Head);
	tmp=Head->next;
	while(1){
		std::cout<<tmp->value<<std::endl;
		if(tmp->next==NULL)
			break;
		tmp=tmp->next;
	}

}