面试问题5:从尾到头打印链表
题目:输入一个链表的头结点,从尾到头反过来打印出每个结点的值。
题目解析:一般从尾到头打印链表结点的值的话,可以想到将链表结点的指针反转过来,改变链表方向,这样相当于从头到尾输出了,但是这样就改变了链表的结构。打印通常只是一个只读操作,并不希望改变链表的数据结构,显然这样的方法是不可行的。
(1)解决这个问题肯定要遍历链表的,遍历的顺序是从头到尾,而输出结果却是从尾到头,,典型的后进先出,这个特点
正是栈的特点。每经过一个结点的时候,我们可以将结点放进栈中,遍历完整个链表后,我们再从栈顶依次输出结点的值。
这样结点的值就能反转输出了。
示例代码:
public class StackPrintLinkedList {
public static void main(String args[]){
ListNode node1 = new ListNode();
ListNode node2 = new ListNode();
ListNode node3 = new ListNode();
node1.data = 1;
node2.data = 2;
node3.data = 3;
node1.next = node2;
node2.next = node3;
printListReverse(node1);
}
public static void printListReverse(ListNode headNode){
Stack<ListNode> stack = new Stack<ListNode>();
while (headNode != null){
stack.push(headNode);
headNode = headNode.next;
}
while (!stack.isEmpty()){
System.out.println(stack.pop().data);
}
}
}
public class ListNode {
public ListNode next;
public int data;
}
(2)递归的本身就是一个栈结构,所以这个问题也可以用递归来实现。每当访问到一个结点的时候,我们先递归输出它后 面的结点,直到递归到最后一个结点时,再返回来输出结点自身。 示例代码:
public class PrintLinkedList {
public static void main(String args[]) {
ListNode node1 = new ListNode();
ListNode node2 = new ListNode();
ListNode node3 = new ListNode();
node1.data = 1;
node2.data = 2;
node3.data = 3;
node1.next = node2;
node2.next = node3;
printListReverse(node1);
}
public static void printListReverse(ListNode headNode) {
if (headNode != null) {
if (headNode.next != null) {
printListReverse(headNode.next);
}
}
System.out.println(headNode.data);
}
}
public class ListNode {
public ListNode next;
public int data;
}
用递归来实现虽然简单,但是当链表非常长的时候,会导致递归函数的层数非常深,有可能导致栈溢出。因此用栈基于 循环实现的鲁棒性好一些。