2012-11-11 38 views
1

這可能嗎?還是會有一個丟失的名單?原因我無法檢查其工作與否釋放整個鏈表,這個算法是否正確?

void FreeRecurs(struct nodeTag *pFirst) 
{ 
    if(pFirst != NULL) 
    { 
      FreeRecurs(pFirst -> pNext); 
      free(pFirst); 
    } 
} 
+0

看起來像它會工作。但是你有沒有研究過使用遞歸的含義?例如,如果你的列表很長,會發生什麼? – Marvo

+0

我認爲它會工作,但爲了清晰起見,請將「pFirst」重命名爲「node」之類的東西 – Imran

回答

6

這將起作用,但在長列表中,您可能會因爲遞歸很多而沒有使用尾遞歸來獲得堆棧溢出。雖然當前的節點不是空

    • 存放指向下一個節點我移動到一個迭代版本。
    • 釋放當前節點。
    • 使用您在釋放前存儲的指針開始處理下一個節點。
1

此算法將工作。也就是說,你應該學會使用像valgrindgdb這樣的工具來監視你的代碼到底發生了什麼,所以你可以判斷它是否工作。

1

我不會用遞歸和的東西,而不是去像這樣:

void FreeRecurs(struct nodeTag *pFirst) 
{ 
    struct nodeTag *aux = NULL; 
    while (pFirst != NULL) 
    { 
     aux = pFirst; 
     pFirst = pFirst -> pNext; 
     free(aux); 
    } 
} 

遞歸導致堆棧溢出,實際上最終是慢,因爲每個函數調用一個新的調用堆棧真的沒有創造。

+0

@Marvo已更正;) – rlgomes

+3

我可能錯了,但我不認爲每個函數都會獲得新的調用堆棧。相反,它會在堆棧上放置一個新框架,是的?當然,不同的編譯器/解釋器可能會以不同的方式實現。 – Marvo

2

理論上,這是好的,但你可以在很大程度上通過使尾遞歸的改進:

void FreeRecurs(struct nodeTag *pFirst) 
{ 
    if(pFirst != NULL) 
    { 
      struct nodeTag* const next = pFirst->pNext; 
      free(pFirst); 
      FreeRecurs(next); 
    } 
} 

注意FreeRecurs(next)現在是在你的函數的最後陳述。編譯器會認識到這一點,你的代碼將運行得更快,並且不會有粉碎堆棧的風險。

除此之外,無論何時不確定是否丟失內存,都可以在valgrind(特別是massif)中運行程序,它會告訴您內存是否丟失。

+0

我應該學會如何使用? valgrind或gdb?有什麼區別嗎? – latenightcode

+0

@vincentbelkin:Valgrind可以幫助您找到內存泄漏。 GDB允許您逐步執行代碼並在運行時檢查值。 – icktoofay