經典算法——單鏈表反轉的遞歸方法和非遞歸方法

單鏈表反轉有遞歸和非遞歸兩種實現方法,

首先定義鏈表結點:

//定義一個鏈表節點
struct ListNode
{
	int value;
	ListNode *next;
};


一、遞歸方法

先反轉後面的鏈表,從最後面的兩個結點開始反轉,依次向前,將後一個鏈表結點指向前一個結點,注意每次反轉後要將原鏈表中前一個結點的指針域置空,表示將原鏈表中前一個結點指向後一個結點的指向關係斷開。




二、非遞歸方法

利用兩個結點指針和一箇中間結點指針temp(用來記錄當前結點的下一個節點的位置),分別指向當前結點和前一個結點,每次循環讓當前結點的指針域指向前一個結點即可,翻轉結束後,記得將最後一個節點的鏈域置爲空。




整體測試程序:

#include<iostream>
using namespace std;

//定義一個鏈表節點
struct ListNode
{
	int value;
	ListNode *next;
};

//插入一個新節點到鏈表中(放在鏈表頭部)
void CreateList(ListNode * & head, int data)
{
	//創建新節點
	ListNode * p = (ListNode*)malloc(sizeof(ListNode));
	p->value = data;
	p->next = NULL;

	if (head == NULL)
	{
		head = p;
		return;
	}
	p->next = head;
	head = p;
}

void  printList(ListNode* head)
{
	ListNode * p = head;
	while (p != NULL)
	{
		cout << p->value<< " ";
		p = p->next;
	}
	cout << endl;
}


//遞歸方式:實現單鏈表反轉
ListNode * ReverseList(ListNode * head)
{
	//遞歸終止條件:找到鏈表最後一個結點
	if (head == NULL || head->next == NULL)
		return head;
	else
	{
		ListNode * newhead = ReverseList(head->next);//先反轉後面的鏈表,從最後面的兩個結點開始反轉,依次向前
		head->next->next = head;//將後一個鏈表結點指向前一個結點
		head->next = NULL;//將原鏈表中前一個結點指向後一個結點的指向關係斷開
		return newhead;
	}
}

//非遞歸方式:實現單鏈表反轉
ListNode* reverseList2(ListNode* head) {
	if (head == NULL || head->next == NULL) 
		return head;
	ListNode* prev = head;
	ListNode* cur = head->next;
	ListNode* temp = head->next->next;

	while (cur){
		temp = cur->next; //temp作爲中間節點,記錄當前結點的下一個節點的位置
		cur->next = prev;  //當前結點指向前一個節點
		prev = cur;     //指針後移
		cur = temp;  //指針後移,處理下一個節點
	}

	head->next = NULL; //while結束後,將翻轉後的最後一個節點(即翻轉前的第一個結點head)的鏈域置爲NULL
	return prev;
}


int main()
{
	ListNode * head = NULL;
	for (int i = 0; i<9; i++)
		CreateList(head, i);
	printList(head);
	head = ReverseList(head);
	printList(head);
	system("pause");
	return 0;
}




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章