一、題目:從尾到頭打印鏈表
題目:輸入一個鏈表的頭結點,從尾到頭反過來打印出每個結點的值。
到解決這個問題肯定要遍歷鏈表。遍歷的順序是從頭到尾的順序,可輸出的順序卻是從尾到頭。也就是說第一個遍歷到的結點最后一個輸出,而最后一個遍歷到的結點第一個輸出。這就是典型的“后進先出”,我們可以用棧實現這種順序。
二、解題思路
每經過一個結點的時候,把該結點放到一個棧中。當遍歷完整個鏈表后,再從棧頂開始逐個輸出結點的值,此時輸出的結點的順序已經反轉過來了。
三、解決問題
3.1 代碼實現
這里使用的是自定義實現的鏈表類,其節點定義如下:
public class Node<T> { // 數據域 public T Item { get; set; } // 指針域 public Node<T> Next { get; set; } public Node() { } public Node(T item) { this.Item = item; } }
這里的自定義的單鏈表的實現請參考:《數據結構基礎溫故-1.線性表(中)》
(1)基於棧的循環版本
public static void PrintListReversinglyIteratively(Node<int> head) { Stack<Node<int>> stackNodes = new Stack<Node<int>>(); Node<int> node = head; // 單鏈表元素依次入棧 while (node != null) { stackNodes.Push(node); node = node.Next; } // 棧中的單鏈表元素依次出棧 while (stackNodes.Count > 0) { Node<int> top = stackNodes.Pop(); Console.Write("{0}", top.Item); } }
(2)遞歸版本
public static void PrintListReversinglyRecursively(Node<int> head) { if (head != null) { if (head.Next != null) { PrintListReversinglyRecursively(head.Next); } Console.Write("{0}", head.Item); } }
兩個版本的對比:上面的基於遞歸的代碼看起來很簡潔,但有個問題:當鏈表非常長的時候,就會導致函數調用的層級很深,從而有可能導致函數調用棧溢出。顯式用棧基於循環實現的代碼的魯棒性要好一些。
3.2 單元測試
(1)單元測試主入口
// 測試主入口 static void PrintTestPortal(Node<int> head) { Console.WriteLine("-------Begin--------"); NormalPrint(head); Console.WriteLine(); PrintListReversinglyIteratively(head); Console.WriteLine(); PrintListReversinglyRecursively(head); Console.WriteLine("\n-------End--------"); } // 輔助方法:正序打印鏈表 static void NormalPrint(Node<int> head) { Node<int> temp = head; while(temp != null) { Console.Write("{0}",temp.Item); temp = temp.Next; } }
在測試入口中,我們首先正序打印鏈表,然后使用循環版從尾到頭打印鏈表,最后使用遞歸版從尾到頭打印鏈表。
(2)正常的多元素鏈表
// 1->2->3->4->5 static void PrintTest1() { Console.WriteLine("TestCase1:"); SingleLinkedList<int> linkedList = new SingleLinkedList<int>(); linkedList.Add(1); linkedList.Add(2); linkedList.Add(3); linkedList.Add(4); linkedList.Add(5); PrintTestPortal(linkedList.Head); }
(3)只有一個節點的鏈表
// 只有一個節點的鏈表 static void PrintTest2() { Console.WriteLine("TestCase2:"); SingleLinkedList<int> linkedList = new SingleLinkedList<int>(); linkedList.Add(1); PrintTestPortal(linkedList.Head); }
(4)魯棒性測試:NULL
// 空鏈表 static void PrintTest3() { Console.WriteLine("TestCase3:"); PrintTestPortal(null); }
測試結果如下圖所示: