本文轉自:http://zhedahht.blog.163.com/blog/static/2541117420079237185699/
題目:輸入一個鏈表的頭結點,從尾到頭反過來輸出每個結點的值。鏈表結點定義如下:
struct ListNode
{
int m_nKey;
ListNode* m_pNext;
};
分析:這是一道很有意思的面試題。該題以及它的變體經常出現在各大公司的面試、筆試題中。
看到這道題後,第一反應是從頭到尾輸出比較簡單。於是很自然地想到把鏈表中鏈接結點的指針反轉過來,改變鏈表的方向。然後就可以從頭到尾輸出了。
接下來的想法是從頭到尾遍歷鏈表,每經過一個結點的時候,把該結點放到一個棧中。當遍歷完整個鏈表後,再從棧頂開始輸出結點的值,此時輸出的結點的順序已經反轉過來了。該方法需要維護一個額外的棧,實現起來比較麻煩。
既然想到了棧來實現這個函數,而遞歸本質上就是一個棧結構。於是很自然的又想到了用遞歸來實現。要實現反過來輸出鏈表,我們每訪問到一個結點的時候,先遞歸輸出它後面的結點,再輸出該結點自身,這樣鏈表的輸出結果就反過來了。
基於這樣的思路,不難寫出如下代碼:
void ReversePrint(ListNode* pHead)
{
if(NULL == pHead)
return;
if(pHead->m_pNext != NULL)
ReversePrint(pHead->m_pNext);
cout<<pHead->m_iValue;
}
從尾到頭輸出一個字符串:
void ReversePrintStr(char* pStr)
{
if(NULL == pStr || '\0'== *pStr)
return;
ReversePrintStr(pStr+1);
cout<<*pStr;
}
定義一個函數求字符串的長度,要求該函數體內不能聲明任何變量:
int StrLen(char* pStr)
{
if(NULL == pStr || *pStr == '\0')
return 0;
return 1+StrLen(pStr+1);
}