Day10 从头到尾打印链表

  • 复习了一下链表,以前用C实现过,现在用Java实现了一下,实现了一些最基本的操作,并测试了一下。之后学到LinkedList类的时候再比较一下。
  • C/C++和Java还是有很多不同的,Java中全部都成了类,没有了结构体,也没有了头文件,也不需要指针,链表实现起来比C方便些。以后要总结一下两个高级语言的一些区别。
package LinkList;

public class LinkListDemo {
    public static void main(String[] args) {
        // 创建链表和结点
        LinkList l = new LinkList();
        ListNode node1 = new ListNode(1);
        ListNode node2 = new ListNode(2);
        ListNode node3 = new ListNode(3);

        // 插入结点
        l.addNode(node1);
        l.addNode(node2);
        l.addNode(node3);

        // 遍历输出
        l.outputList();
    }
}

// 单链表结点的定义
class ListNode {
    int val; // 存放节点数据域
    ListNode next = null; // 指向下一个节点
    // 构造方法
    ListNode(int val) {
        this.val = val;
    }
}

// 单链表的相关操作集
class LinkList {
    // 初始化链表
    private ListNode head = new ListNode(0); // 初始化头结点

    // 尾插法添加结点
    public void addNode(ListNode listNode) {
        ListNode temp = head; // 辅助遍历链表
        while(true) {
            // 找到尾结点
            if(temp.next == null) {
                break;
            }
            // 继续查找
            temp = temp.next;
        }
        // 最后结点指向新的结点
        temp.next = listNode;
    }

    // 输出单链表数据
    public void outputList() {
         // 判断链表是否为空
        if (head.next == null) {
            System.out.println("链表为空");
            return;
        }
        ListNode temp = head.next; // 辅助遍历链表
        while(true) {
            if(temp == null) {
                break;
            }
            // 输出数据,指针后移
            System.out.println(temp.val);
            temp = temp.next;
        }
    }
}




题目:输入一个链表的头节点,从尾到头反过来打印出每个节点的值。'
链表节点与题目定义如下:

class ListNode {
    int val;
    ListNode next = null;
    ListNode(int val) {
        this.val = val;
    }
}

import java.util.ArrayList;
public class Solution {
    public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
        
    }
}
  • 算法分析:如何实现从头到尾输出?
    • 可改变结构:让链表的指针反转即可。
    • 不改变结构:所以可以用栈进行递归。
  • 程序分析:牛客网给到的结点与函数定义中
    • 输出值类型为ArrayList,输入值为链表结点
    • 不可以直接使用LinkedList类,可以使用ArrayList类
  • 解决问题:最简单的还是调用API,ArrayList.add(index,value)方法就很方便
  • 多种解法:不改变结构的话,栈可以用系统栈和API中的Stack类
  • 方法分析:三种方法的复杂度差不多,都是O(n)。但是算法练习中少用API的好,所以用系统栈来进行递归是最应景的,但缺点是链表太长可能会使栈溢出。
  • 一些细节:输入结点应为链表的首元结点,不需要头结点。(程序中不需要插入、删除操作)
package LinkList;
/*题目:输入一个链表的头节点,从尾到头反过来打印出每个节点的值。'
链表节点定义如下:
class ListNode {
    int val;
    ListNode next = null;
    ListNode(int val) {
        this.val = val;
    }
}
*/

import java.util.ArrayList;
import java.util.Stack;
public class PrintListFromTailToHead {
    public static void  main(String[] args){
        // 初始化链表和结点
        LinkList l = new LinkList();
        ListNode node1 = new ListNode(1);
        ListNode node2 = new ListNode(2);
        ListNode node3 = new ListNode(3);

        // 插入结点
        l.addNode(node1);
        l.addNode(node2);
        l.addNode(node3);

        // 遍历输出
//        l.outputList();
        ArrayList<Integer> list = printListFromTailToHead1(node1); // 输入首元结点,创建逆序链表
        for(int i = 0; i < list.size(); i++) {
            System.out.println(list.get(i));
        }
    }

    // 非递归:利用 ArrayList.add(index,value),可以指定 index 位置插入 value 值
    // 遍历链表的同时将每个遇到的值插入到 ArrayList 的 0 位置(头插法),最后输出即可得到逆序链表。
    public static ArrayList<Integer> printListFromTailToHead1(ListNode listNode) {
        ArrayList<Integer> list = new ArrayList<>();
        // 辅助元素遍历链表
        ListNode tmp = listNode;
        // 结点不为空,则插入 list 头部,并移动指针
        while(tmp !=null){
            list.add(0,tmp.val);
            tmp = tmp.next;
        }
        return list;
    }

    // 因为是从头到尾输出,也就是先进后出,要用递归,也就是用栈来实现。
    // 缺点是链表太长可以会使栈溢出。
    // 递归方法:使用Stack类
    public static ArrayList<Integer> printListFromTailToHead2(ListNode listNode) {
        ArrayList<Integer> list = new ArrayList<>();
        Stack<Integer> stack = new Stack<>();
        while (listNode != null) {
            stack.push(listNode.val);
            listNode = listNode.next;
        }
        while (!stack.isEmpty()) {
            list.add(stack.pop());
        }
        return list;
    }
    // 递归方法:使用系统栈
    public ArrayList printListFromTailToHead3(ListNode listNode) {
        ArrayList list = new ArrayList();
        if(listNode!=null){
            printListFromTailToHead3(listNode.next);
            list.add(listNode.val);
        }
        return list;
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值