這可能嗎?還是會有一個丟失的名單?原因我無法檢查其工作與否釋放整個鏈表,這個算法是否正確?
void FreeRecurs(struct nodeTag *pFirst)
{
if(pFirst != NULL)
{
FreeRecurs(pFirst -> pNext);
free(pFirst);
}
}
這可能嗎?還是會有一個丟失的名單?原因我無法檢查其工作與否釋放整個鏈表,這個算法是否正確?
void FreeRecurs(struct nodeTag *pFirst)
{
if(pFirst != NULL)
{
FreeRecurs(pFirst -> pNext);
free(pFirst);
}
}
這將起作用,但在長列表中,您可能會因爲遞歸很多而沒有使用尾遞歸來獲得堆棧溢出。雖然當前的節點不是空
此算法將工作。也就是說,你應該學會使用像valgrind
或gdb
這樣的工具來監視你的代碼到底發生了什麼,所以你可以判斷它是否工作。
我不會用遞歸和的東西,而不是去像這樣:
void FreeRecurs(struct nodeTag *pFirst)
{
struct nodeTag *aux = NULL;
while (pFirst != NULL)
{
aux = pFirst;
pFirst = pFirst -> pNext;
free(aux);
}
}
遞歸導致堆棧溢出,實際上最終是慢,因爲每個函數調用一個新的調用堆棧真的沒有創造。
理論上,這是好的,但你可以在很大程度上通過使尾遞歸的改進:
void FreeRecurs(struct nodeTag *pFirst)
{
if(pFirst != NULL)
{
struct nodeTag* const next = pFirst->pNext;
free(pFirst);
FreeRecurs(next);
}
}
注意FreeRecurs(next)
現在是在你的函數的最後陳述。編譯器會認識到這一點,你的代碼將運行得更快,並且不會有粉碎堆棧的風險。
除此之外,無論何時不確定是否丟失內存,都可以在valgrind
(特別是massif
)中運行程序,它會告訴您內存是否丟失。
我應該學會如何使用? valgrind或gdb?有什麼區別嗎? – latenightcode
@vincentbelkin:Valgrind可以幫助您找到內存泄漏。 GDB允許您逐步執行代碼並在運行時檢查值。 – icktoofay
看起來像它會工作。但是你有沒有研究過使用遞歸的含義?例如,如果你的列表很長,會發生什麼? – Marvo
我認爲它會工作,但爲了清晰起見,請將「pFirst」重命名爲「node」之類的東西 – Imran