1. 程式人生 > >C++使用迭代和遞迴兩種方式實現連結串列逆序演算法

C++使用迭代和遞迴兩種方式實現連結串列逆序演算法

1.連結串列逆序的兩種演算法

      C++實現一個連結串列逆序演算法

2.連結串列逆序演算法實現原理

如A->B->C->D->E,一般會有以下兩種思路,如下

思路1:

先取出連結串列的最後一個E,然後將E作為新連結串列的頭,

現在狀態為

原始連結串列:A->B->C->D

新連結串列:E

再取出原來連結串列的最後一個D,然後將D插入到新連結串列的最後位置,

現在狀態為

原始連結串列:A->B->C

新連結串列:E->D

依次類推,最後形成E->D->C->B->A

可以看出來,這個演算法的複雜度為O(n2)。

思路二:

取出原始連結串列的第一個節點A,然後將該節點作為新連結串列的頭節點。

現在狀態為

原始連結串列:B->C->D->E

新連結串列:A

然後同上,變為了下面的狀態

原始連結串列:C->D->E

新連結串列: B->A

原始連結串列:D->E

新連結串列: C->B->A

原始連結串列:E

新連結串列: D->C->B->A

原始連結串列:

新連結串列: E->D->C->B->A

這個只需要對原始連結串列遍歷一次,就完成了這個工作,所以這個演算法的複雜度為O(n)。
        通過對上面狀態的變化分析,只要我們知道原始連結串列和新連結串列的頭節點,我們就可以從原始連結串列取出第一個節點,然後將節點插入到新連結串列的第一個位置,由於兩個連結串列的頭結點現在都已經變化,所以我們不能丟失新頭節點的地址。所以,我們要設定兩個變數分別記錄兩個連結串列的頭結點。下面程式中的old_head和 new_head分別表示原始連結串列的頭節點和新連結串列的頭節點。

// ListReverse.cpp : 定義控制檯應用程式的入口點。
//
#include "stdafx.h"
#include <stdio.h>
#include <malloc.h>

typedef struct Node {
	int data;
	struct Node* next;
}Node;

#define LIST_LEN     10     //連結串列長度
Node * List = NULL;          //連結串列

//迭代方式
void reverse_ite(Node * list) {
	Node * old_head = NULL;         //原來連結串列的頭
	Node * new_head = NULL;      //新連結串列的頭
	Node * cur = list;      //獲得原來連結串列的頭

							//每次將原來連結串列的頭取出,並插入到新連結串列中,並且是新連結串列的頭
	while (cur != NULL) {
		old_head = cur->next;      //將原來連結串列的頭取出,並將第二個節點作為頭節點
		cur->next = new_head;   //將取出的頭設為新連結串列的頭

		new_head = cur;      //新連結串列的頭就是目前新連結串列的頭
		cur = old_head;        //接著處理
	}

	List = new_head;
}

//遞迴方式
void reverse_recursive(Node * old_head, Node * new_head) {
	if (old_head == NULL) {
		List = new_head;
		return;
	}

	Node * tmp = old_head->next;        //將原來連結串列的頭取出,並將第二個節點作為原來連結串列的頭節點用於下一層遞迴
	old_head->next = new_head; //將取出的頭設為新連結串列的頭
	reverse_recursive(tmp, old_head);         //接著處理
}

//生成連結串列
void make_list() {
	List = (Node *)malloc(sizeof(Node) * LIST_LEN);
	int i = 0;
	for (i = 0; i < (LIST_LEN - 1); i++) {
		(List + i)->data = i + 1;
		(List + i)->next = List + i + 1;
	}
	(List + LIST_LEN - 1)->data = LIST_LEN;
	(List + LIST_LEN - 1)->next = NULL;
}

//列印倆表的data
void print_list() {
	Node * cur = List;
	while (cur != NULL) {
		printf("%d ", cur->data);
		cur = cur->next;
	}
	printf("\n");
}

int main() {
	make_list();
	print_list();
	//迭代方式
	reverse_ite(List); 
	print_list();
	//遞迴方式
	reverse_recursive(List, NULL);
	print_list();
}

程式碼執行結果如下: