单链表的 Java 语言实现

之前有写过一篇单链表的 C 语言实现,现在写一篇 Java 的实现

链表节点单独定义成一个静态内部类

public class TestListNode {
    public static void main(String[] args) {
        ListNode head = createListNode(7);
        System.out.print("初始链表结构: ");
        trverseNodeList(head.next);
       
//        System.out.print("翻转后的链表结构: ");
//        ListNode newHead = reverseNodeList(head.next);
//       trverseNodeList(newHead);

//        System.out.print("反转链表前 N 个节点: ");
//        ListNode newHead = reverseN(head.next, 2);
//        trverseNodeList(newHead);

        System.out.print("反转链表的一部分 ");
        ListNode newHead = reverseBetween(head.next, 3, 5);
        trverseNodeList(newHead);
    }

    /**
     * 链表的反转,递归方式
     *
     * @param head 原链表的首节点
     * @return 返回新链表的首节点,注意翻转后的链表没有了头结点
     */
    private static ListNode reverseNodeList(ListNode head) {
        if (head == null || head.next == null) return head;
        ListNode last = reverseNodeList(head.next);
        head.next.next = head;
        head.next = null;
        return last;
    }

    private static ListNode successor;

    /**
     * 反转链表前 N 个节点
     *
     * @param head 原链表的首节点
     * @return 返回新链表的首节点,注意翻转后的链表没有了头结点
     */
    private static ListNode reverseN(ListNode head, int n) {
        if (n == 1) {
            successor = head.next;
            return head;
        }
        // 以 head.next 为起点,需要反转前 n - 1 个节点
        ListNode last = reverseN(head.next, n - 1);
        head.next.next = head;
        head.next = successor;
        return last;
    }

    /**
     * 反转链表的一部分
     * 给定区间[m, n]
     */
    private static ListNode reverseBetween(ListNode head, int m, int n) {
        if (m == 1) {
            // 相当于反转前 n 个元素
            return reverseN(head, n);
        }
        head.next = reverseBetween(head.next, m - 1, n - 1);
        return head;
    }

    private static void trverseNodeList(ListNode head) {
        if (head == null || head.next == null) return;
        while (head != null) {
            System.out.print(head.val + " ");
            head = head.next;
        }
        System.out.println();
    }

    private static ListNode createListNode(int n) {
        ListNode head = new ListNode();
        ListNode last = head;
        for (int i = 1; i <= n; i++) {
            ListNode newNode = new ListNode(i);
            last.next = newNode;
            last = newNode;
            last.next = null;
        }
        return head;
    }

    static class ListNode {
        Integer val;
        ListNode next;

        public ListNode() {
        }

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

可以看到,这里把 ListNode 定义成一个静态内部类,否则是不能通过 head.next 这样直接访问实例变量,这种写法也是比较简洁

链表节点单独定义成一个类

定义节点类型

public class ListNode {
    private Integer val;
    private ListNode next;

    public ListNode() {}

    public ListNode(Integer val, ListNode next) {
        this.val = val;
        this.next = next;
    }

    public Integer getVal() {
        return val;
    }

    public void setVal(Integer val) {
        this.val = val;
    }

    public ListNode getNext() {
        return next;
    }

    public void setNext(ListNode next) {
        this.next = next;
    }
}

在类中使用,这里直接贴出代码实现

public class TestListNode {
    public static void main(String[] args) {
        ListNode head = createListNode( 8);
        // 因为创建链表的时候多了个头结点,这里跳过头结点进行遍历
        traverseListNode(head.getNext());
        ListNode newHead = reverseListNode(head.getNext());
        traverseListNode(newHead);
    }

    /**
     * 链表的反转
     *
     * @param head 原链表的首节点
     * @return 返回新链表的首节点,注意翻转后的链表没有了头结点
     */
    private static ListNode reverseListNode(ListNode head) {
        if (head == null || head.getNext() == null) return head;
        ListNode last = reverseListNode(head.getNext());
        // 注意这种 getNext 方式和后续介绍的 head.next 方式区别
        head.getNext().setNext(head);
        head.setNext(null);
        return last;
    }

    private static void traverseListNode(ListNode head) {
        if (head == null || head.getNext() == null) return;
        // 这种方式不大好,一轮循环下来改变了 head 的值
//        while (head.getNext() != null) {
//            System.out.print(head.getNext().getVal()+" ");
//            head = head.getNext();
//        }

        // 推荐这种方式,定义一个临时指针
        ListNode tmpNode = head;
        // 跳过头结点,头结点的数据域是 null
        while (tmpNode != null) {
            System.out.print(tmpNode.getVal()+" ");
            tmpNode = tmpNode.getNext();
        }
        System.out.println();
    }

    /**
     * 创建链表
     *
     * @param n 链表的个数
     * @return 返回头指针
     */
    private static ListNode createListNode(int n) {
        // 定义一个头指针,指向头结点,便于对链表的操作
        ListNode head = new ListNode(null, null);
        // 初始时刻,尾指针指向头结点
        ListNode tail = head;
        for (int i = 1; i <= n; i++) {
            ListNode newNode = new ListNode();
            newNode.setVal(i);
            tail.setNext(newNode);
            tail = newNode;
            tail.setNext(null);
        }
        return head;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值