所以有兩種方法可以遞歸地反轉列表。
首先,一些設置。讓我們可以很容易地加載鏈表串 並打印出來,所以我們可以肯定這東西的作品:
倒車列表
// linked_list.c
#include <stdio.h>
#include <stdlib.h>
// a linked lis of strings
typedef struct S {
struct S * next;
char * val;
} S;
// print out the list
void showS(char * const name, S * head) {
printf("%s: (", name);
while (head){
printf(" ");
printf("%s",head->val);
head = head->next;
printf("%c", head ? ',' : ' ');
}
printf(")\n");
}
// convert an array of strings into a linked list of strings
S * mkS(int n, char ** args) {
S * head = NULL;
if (n > 0 && (head = calloc(n, sizeof(S)))){
S * curr = head - 1;
while (n-- > 0) {
curr++;
curr->val = *args++;
curr->next = curr + 1;
}
curr->next = NULL;
}
return head;
}
一種方式包括使 列表後面的新掌門人,一旦我們找到它。我們本地不需要它(因爲我們只是將當前元素移動到新的末端),但是我們需要它,以便調用者 在完成後有一個指向列表頭的指針。
// reverse a list one way
S * revS1(S * const head){
if (head && head->next) {
S * const new_head = revS1(head->next);
head->next->next = head;
head->next = NULL;
return new_head;
} else {
return head;
}
}
另一種方法需要一個指針指針。唯一的區別是 我們不需要返回任何東西,因爲我們直接修改調用者具有的變量 。我更喜歡這種調用方法,因爲它更清晰 我們正在修改列表,而不是返回副本。呼叫者以這種方式意外鬆開指向新頭部的指針也很難。
// reverse a list another way
void revS2(S ** phead){
S * const head = *phead;
if (head && head->next) {
*phead = head->next;
revS2(phead);
head->next->next = head;
head->next = NULL;
}
}
但是,比這兩者中的任何一個都更好的是以非遞歸方式反轉列表。 這兩個函數都不是尾遞歸的,所以編譯器有 爲列表中的每個元素分配新的堆棧幀。嘗試將足夠的列表反轉一個長的列表,然後你就會炸燬你的堆棧。更好地使用while循環來逆轉列表 。
// reverse a list non-recursively
void revS3(S ** phead){
S * head = *phead;
S * reversed = NULL;
while (head) {
S * curr = head;
head = curr->next;
curr->next = reversed;
reversed = curr;
}
*phead = reversed;
}
現在我們可以只通過建立列出了命令行的測試我們的研究結果:
// just use the command line arguments as our list
int main(int argc, char** argv){
S* list1 = mkS(argc - 1, argv + 1);
S* list2 = mkS(argc - 1, argv + 1);
S* list3 = mkS(argc - 1, argv + 1);
showS("given", list1);
showS("revS1", revS1(list1));
revS2(&list2);
showS("revS2", list2);
revS2(&list3);
showS("revS3", list3);
return 0;
}
因此,讓我們編譯:
% gcc -Wall linked_list.c -o linked_list
,並做一些測試運行
% ./linked_list
given:()
revS1:()
revS2:()
revS3:()
% ./linked_list first second third
given: (first, second, third)
revS1: (third, second, first)
revS2: (third, second, first)
revS3: (third, second, first)
% ./linked_list only
given: (only)
revS1: (only)
revS2: (only)
revS3: (only)
拍攝。你必須有一些東西從遞歸調用中獲得回報。我相信這是你的代碼的核心問題。 – Jiminion
順便說一句:建議改變'return;'返回NULL;' – chux