【剑指offer】面试题五:从尾到头打印链表
题目:输入一个链表的头结点,从尾到头反过来打印出每个结点的值。
链表结点定义如下:
typedef struct Node { int m_nKey; struct Node *m_pNext; }ListNode, *pListNode;
我们可能会想到把链表结点的指针反转过来,改变链表的方向,然后就可以从头到尾输出了。但是这种方法改变了链表原来的结构。
但是,一般的如打印这样的只读操作,我们一般不会去改变其原来的结构。
而如果我们要想解决这个问题,就必须要遍历链表。遍历的顺序是从头到尾,可输出的顺序却是从尾到头。
也就是说第一个遍历到的元素最后一个输出;而最后一个遍历到的元素第一个输出。显然我们可以利用栈“先进后出”的规律来帮助我们解决这个问题。
具体步骤:
1、从头到尾遍历元素,同时将其放进栈中;
2、弹出栈顶元素,直到栈为空。
在借助栈的情况下,我们不难写出如下代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 // printListReversely.cpp 2 #include "stdio.h" 3 #include "stdlib.h" 4 #include <stack> 5 #define N 20 6 7 typedef struct Node 8 { 9 int m_nKey; 10 struct Node *m_pNext; 11 }ListNode; 12 13 void printList(ListNode *pHead) 14 { 15 while(pHead != NULL) 16 { 17 printf("%3d", pHead->m_nKey); 18 pHead = pHead->m_pNext; 19 } 20 printf("\n"); 21 } 22 23 void createList(ListNode **pHead, int len) 24 { 25 if(len < 0) 26 return; 27 28 ListNode *pTail = NULL; 29 30 while(len > 0) 31 { 32 ListNode *pNew = (ListNode*)malloc(sizeof(ListNode)); 33 pNew->m_pNext = NULL; 34 pNew->m_nKey = rand()%100; 35 36 if(*pHead == NULL) 37 { 38 *pHead = pNew; 39 pTail = pNew; 40 } 41 else 42 { 43 pTail->m_pNext = pNew; 44 pTail = pNew; 45 } 46 len--; 47 } 48 } 49 50 void printListReversely(ListNode *pHead) 51 { 52 std::stack<ListNode*> st; 53 54 while(pHead != NULL) 55 { 56 st.push(pHead); 57 pHead = pHead->m_pNext; 58 } 59 60 while(!st.empty()) 61 { 62 printf("%3d", (st.top())->m_nKey); 63 st.pop(); 64 } 65 printf("\n"); 66 } 67 68 69 int main(int argc, char const *argv[]) 70 { 71 ListNode *pHead = NULL; 72 73 createList(&pHead, N); 74 printf("Before:\n"); 75 printList(pHead); 76 77 printf("After:\n"); 78 printListReversely(pHead); 79 80 return 0; 81 }
注:C中并没有Stack的库,如果坚持用C,可自行实现stack的push、pop操作,这里我们用的是.cpp文件。
编译与执行:
1 g++ -o printListReversely printListReversely.cpp 2 ./printListReversely
本文完。