zoukankan      html  css  js  c++  java
  • 面试题四 从尾到头打印链表

    题目

      输入一个链表的头结点,从尾到头反过来打印出每个结点的值。

    分析

      这个题目有三种解法,可以根据实际情况灵活选用。

    解法一 堆栈法

      设立一个堆栈,然后遍历一次链表,其间将数据依次存入堆栈。遍历完之后将所有元素依次出栈并打印即可。

      PS:这里堆栈直接用C++中的stack容器适配器实现

    代码实现( 含测试 )

     1 #include <iostream>
     2 #include <stack>
     3 
     4 using namespace std;
     5 
     6 /*
     7  * 定义结点类型
     8 */
     9 struct ListNode {
    10     int value;
    11     ListNode *next;
    12 };
    13 
    14 // 逆序打印函数
    15 void rPrint(ListNode * head);
    16 
    17 /*
    18  * 测试函数:建立一个链表,有10个结点,结点的值依次为1-10。
    19  *          然后调用rPrint函数将数据从尾到头打印出来。
    20 */
    21 int main()
    22 {
    23     ListNode *head = new ListNode();
    24     head->value = 1;
    25 
    26     ListNode *q = head;
    27     ListNode *p = NULL;
    28 
    29     for (int i=2; i<=10; i++) {
    30         p = new ListNode();
    31         p->value = i;
    32         q->next = p;
    33         q = q->next;
    34     }
    35     p->next = NULL;
    36 
    37     p = head;
    38     cout << "目标链表:" << endl;
    39     while (p != NULL) {
    40         cout << p->value << " ";
    41         p = p->next;
    42     }
    43     cout << endl;
    44 
    45     rPrint(head);
    46 
    47     return 0;
    48 }
    49 
    50 /*
    51  * 逆序打印函数
    52 */
    53 void rPrint(ListNode * head)
    54 {
    55     // 定义一个堆栈( 容器适配器 )
    56     stack<ListNode *> s;
    57 
    58     // 顺序遍历链表并将数据存进堆栈
    59     ListNode *p = head;
    60     while (p!=NULL) {
    61         s.push(p);
    62         p = p->next;
    63     }
    64 
    65     // 所有数据出栈并打印
    66     cout << "逆序打印之:" << endl;
    67     while (!s.empty()) {
    68         p = s.top();
    69         s.pop();
    70         cout << p->value << " ";
    71     }
    72     
    73     cout << endl;
    74 }

    运行测试

      

    解法二 递归法

      递归打印此链表,这也是最简单的解法。

    代码实现( 含测试 )

     1 #include <iostream>
     2 
     3 using namespace std;
     4 
     5 /*
     6  * 定义结点类型
     7 */
     8 struct ListNode {
     9     int value;
    10     ListNode *next;
    11 };
    12 
    13 // 逆序打印函数
    14 void rPrint(ListNode * head);
    15 
    16 /*
    17  * 测试函数:建立一个链表,有10个结点,结点的值依次为1-10。
    18  *          然后调用rPrint函数将数据从尾到头打印出来。
    19 */
    20 int main()
    21 {
    22     ListNode *head = new ListNode();
    23     head->value = 1;
    24 
    25     ListNode *q = head;
    26     ListNode *p = NULL;
    27 
    28     for (int i=2; i<=10; i++) {
    29         p = new ListNode();
    30         p->value = i;
    31         q->next = p;
    32         q = q->next;
    33     }
    34     p->next = NULL;
    35 
    36     p = head;
    37     cout << "目标链表:" << endl;
    38     while (p != NULL) {
    39         cout << p->value << " ";
    40         p = p->next;
    41     }
    42     cout << endl;
    43 
    44     rPrint(head);
    45 
    46     cout << endl;
    47 
    48     return 0;
    49 }
    50 
    51 /*
    52  * 逆序打印函数
    53 */
    54 void rPrint(ListNode * head)
    55 {
    56     if (head == NULL)
    57         return;
    58     
    59     if (head->next != NULL) {
    60         rPrint(head->next);
    61         cout << head->value << " ";
    62     }
    63     else
    64         cout << head->value << " "; // 递归“出口”
    65 }

    运行测试

      

    解法三 临时修改链表法

      如果有些时候要求你不能使用栈或者递归( 内存空间很小 ),这时候应当使用这种方法:

      1. 首先将链表从头到尾翻转一次,同时遍历指针到达表尾。

      2. 然后将链表从尾到头翻转一次,在这次的翻转过程中同时输出结点数据。

    代码实现( 含测试 )

      1 #include <iostream>
      2 
      3 using namespace std;
      4 
      5 /*
      6  * 定义结点类型
      7 */
      8 struct ListNode {
      9     int value;
     10     ListNode *next;
     11 };
     12 
     13 // 逆序打印函数
     14 void rPrint(ListNode * head);
     15 
     16 /*
     17  * 测试函数:建立一个链表,有10个结点,结点的值依次为1-10。
     18  *          然后调用rPrint函数将数据从尾到头打印出来。
     19 */
     20 int main()
     21 {
     22     ListNode *head = new ListNode();
     23     head->value = 1;
     24 
     25     ListNode *q = head;
     26     ListNode *p = NULL;
     27 
     28     for (int i=2; i<=10; i++) {
     29         p = new ListNode();
     30         p->value = i;
     31         q->next = p;
     32         q = q->next;
     33     }
     34     p->next = NULL;
     35 
     36     p = head;
     37     cout << "目标链表:" << endl;
     38     while (p != NULL) {
     39         cout << p->value << " ";
     40         p = p->next;
     41     }
     42     cout << endl;
     43 
     44     rPrint(head);
     45 
     46     return 0;
     47 }
     48 
     49 /*
     50  * 逆序打印函数
     51 */
     52 void rPrint(ListNode * head)
     53 {
     54     /*
     55      * 下面三个if判断分别处理结点数为0,1,2时候的情况。
     56     */
     57     if (head == NULL)
     58         return;
     59     if (head != NULL && head->next == NULL) {
     60         cout << head->value << endl;
     61         return;
     62     }
     63     if (head != NULL && head->next != NULL && head->next->next == NULL) {
     64         cout << head->next->value << " " << head->value << endl;
     65         return;
     66     }
     67 
     68     // 下面是结点数大于等于3时候的处理。
     69 
     70     // 首先,翻转链表一次。
     71     ListNode *s, *p, *q;
     72     q = head; p = head->next; s = head->next->next;
     73     q->next = NULL; // 这步别忘
     74 
     75     while (s != NULL) {
     76         p->next = q;
     77         q = p;
     78         p = s;
     79         s = s->next;
     80     }
     81     // 收尾
     82     p->next = q;
     83 
     84     // 然后,再翻转链表一次。
     85     q = p;
     86     p = q->next;
     87     s = p->next;
     88 
     89     q->next = NULL; // 这步别忘
     90     cout << q->value << " " << p->value << " "; // 先将头两个结点的数据输出
     91     while (s != NULL) {
     92         cout << s->value << " "; // 翻转的过程中输出链表数据
     93         p->next = q;
     94         q = p;
     95         p = s;
     96         s = s->next;
     97     }
     98     // 再次收尾
     99     p->next = q;
    100 
    101     cout << endl;
    102 }

    运行测试

      

    小结

      C++中的容器及容器适配器都挺实用的

  • 相关阅读:
    springmvc
    POJ 3683 Priest John's Busiest Day
    POJ 3678 Katu Puzzle
    HDU 1815 Building roads
    CDOJ UESTC 1220 The Battle of Guandu
    HDU 3715 Go Deeper
    HDU 3622 Bomb Game
    POJ 3207 Ikki's Story IV
    POJ 3648 Wedding
    HDU 1814 Peaceful Commission
  • 原文地址:https://www.cnblogs.com/scut-fm/p/3606400.html
Copyright © 2011-2022 走看看