剑指offer-03-从尾到头打印链表

题目描述* 剑指offer面试题5:从尾到头打印链表
输入一个链表的头结点,从尾到头打印出每个结点的值
解决方案一:首先遍历链表的节点后打印,典型的“后进先出”,可以使用栈来实现这种顺序。
解决方案二:栈的本质就是递归,直接使用递归的方式,打印一个节点的时候先打印它后面的节点,再打印该节点自身,实现反向打印
解决方案三:遍历链表,把链表中的元素复制到ArrayList中,然后逆序打印ArrayList中的元素,由于ArrayList底层使用数组实现,所以用数组也是同样的原理
解决方案四:前三种解决方案本身属于在打印链表的时候不修改链表本身结构,在允许修改链表结构的情况下可以把链表中的节点指针反转过来,改变链表方向,然后重新遍历打印改变方向后的链表。

package com.offer.stack1;

/**
 * @author kankan
 * @creater 2019-05-10 22:50
 */
public class ListNode {

    int value;//数据域
    ListNode next = null;//指向下一节点的引用

    public ListNode() {
    }

    public ListNode(int value) {
        this.value = value;
    }
}

package com.offer.stack1;

/**
 * @author kankan
 * @creater 2019-05-14 17:22
 */
public class LinkStack<T> {

    //定义一个内部类节点,代表链栈的节点
    private class LinkNode{
        //保存节点数据
        private T data;
        //指向下一个节点的引用
        private LinkNode next;

        public LinkNode() {
        }

        public LinkNode(T data, LinkNode next) {
            this.data = data;
            this.next = next;
        }
    }

    //保存该链栈的栈顶元素
    private LinkNode top;

    //保存该链栈中已包含的节点数
    private int size;

    //创建空链栈
    public LinkStack() {
    }

    //返回链栈的长度
    public int length(){
        return size;
    }
    //进栈
    public void push(T element){
        //让top指向新创建的元素,新元素的next引用指向原来的栈顶元素
        top = new LinkNode(element,top);
        size++;
    }
    //出栈
    public T pop(){
        LinkNode oldTop = top;
        //让top引用指向原栈顶元素的下一个元素
        top = top.next;
        //释放原栈顶元素的next引用
        oldTop.next = null;
        size--;
        return oldTop.data;
    }
    //访问栈顶元素,但不删除栈顶元素
    public T peek(){
        return top.data;
    }
    //判断链栈是否为空栈
    public boolean empty(){
        return size == 0;
    }
    //清空链栈
    public void clear(){
        top = null;
        size = 0;
    }

}

package com.offer.stack1;

import java.util.ArrayList;
import java.util.Stack;

/**
 * @author kankan
 * @creater 2019-05-14 16:43
 */
public class Solution3 {
    public static void main(String[] args) {
        ListNode node1=new ListNode(1);
        ListNode node2=new ListNode(2);
        ListNode node3=new ListNode(3);
        ListNode node4=new ListNode(4);

        node1.next=node2;
        node2.next=node3;
        node3.next=node4;
        //方案一
        System.out.println("=================方案一 自己写的栈==============");
        printListFromTailToHeadByStack(node1);
        System.out.println();
        System.out.println("=================方案一==============");
        printListFromTailToHeadByStack1(node1);
        System.out.println();
        System.out.println("=================方案二==============");
        //方案二:递归法逆序打印链表
        printListFromTailToHead(node1);
        System.out.println();
        System.out.println("=================方案三==============");
        //方案三:使用ArrayList逆序打印链表
        printListFromTailToHeadByArrayList(node1);
        System.out.println();
        System.out.println("=================方案四:递归反转链表后,遍历打印==============");
        printListFromTailToHeadByReverseList(node1);

    }
    /*
     * 方案一:通过使用栈结构,遍历链表,把先遍历的节点的值推入栈中,遍历结束后通过弹出栈内元素实现逆序打印
     * 自己写的栈
     */
    public static void printListFromTailToHeadByStack(ListNode node){
        LinkStack<Integer> stack = new LinkStack<Integer>();
        while (node != null){
            stack.push(node.value);
            node = node.next;
        }
        while (! stack.empty()){
            System.out.print(stack.pop() + " ");
        }
    }
    /*
     * 方案一:通过使用栈结构,遍历链表,把先遍历的节点的值推入栈中,遍历结束后通过弹出栈内元素实现逆序打印
     */
    public static void printListFromTailToHeadByStack1(ListNode node){
        Stack<Integer> stack = new Stack<Integer>();
        while (node != null){
            stack.push(node.value);
            node = node.next;
        }
        while (! stack.empty()){
            System.out.print(stack.pop() + " ");
        }
    }
    /*
     * 方案二:递归法逆序打印链表
     */
    public static void printListFromTailToHead(ListNode node){
        if (node != null){
            if (node.next != null){
                //System.out.println("node.value: " + node.value);
                printListFromTailToHead(node.next);
            }
            System.out.print(node.value + " ");
        }else{
            System.out.println("输入的链表为空");
        }
    }
    /*
     * 方案三:使用ArrayList逆序打印链表
     */
    public static void printListFromTailToHeadByArrayList(ListNode node){
        if (node == null){
            System.out.println("输入链表为null");
        }
        ArrayList<Integer> arrayList = new ArrayList<Integer>();
        while (node != null){
            arrayList.add(node.value);
            node = node.next;
        }
        //ArrayList逆序打印链表
        for (int i = arrayList.size() - 1; i >= 0;i--){
            System.out.print(arrayList.get(i) + " ");
        }
    }
    /*
     * 方案四:递归反转链表后,遍历打印
     */
    public static void printListFromTailToHeadByReverseList(ListNode head){
        ListNode reverseNode = reverse(head);
        while (reverseNode != null){
            System.out.print(reverseNode.value + " ");
            reverseNode = reverseNode.next;
        }
    }
    //递归反转
    private static ListNode reverse(ListNode head){
        if (head.next == null){
            return head;//3
        }
        ListNode reverse = reverse(head.next);
        head.next.next = head;//反转链表 3.next.next = 3 ==> 4.next = 3;  2.next.next = 2 ==> 3.next = 2   1.next.next=1 ==> 2.next = 1
        head.next = null;//3.next = null;  2.next = null  1.next = null
        return reverse;
    }
}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值