链表翻转,单向链表,(根据步长翻转)

直接上代码,思路什么的都在代码中

package com.jiyx.tesr.testLinked;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * auther: jiyx
 * date: 2018/9/11.
 */
public class LinkedUtils {

    /**
     * 定义链表节点
     */
    @AllArgsConstructor
    @NoArgsConstructor
    @Data
    private static class Node {
        private int value;
        private Node next;
    }

    /**
     * 创建链表
     * @param len
     * @return
     */
    private static Node createNode(int len) {
        if (len <= 0) {
            return null;
        } else {
            return new Node(len, createNode(--len));
        }
    }

    /**
     * 这里是单向链表,所以如果翻转的时候是从中间节点开始的话,会丢失前面的节点
     * 思路:获取当前节点,然后让当前节点指向他的头结点,然后他的下一个节点指向他
     * 这个是自己第一时间想到的,是最麻烦的
     *
     * @param node
     * @return
     */
    public static Node reverse(Node node) {
        Node curr = null;
        Node next = null;
        Node dNext = node;
        Node pNext = null;
        while (dNext != null) {
            // 设置当前节点
            curr = dNext;
            // 获取下一位的节点
            next = curr.getNext();
            // 将当前的链表和已经反转的链表相连
            curr.setNext(pNext);
            if (next != null) {
                // 获取链表的第三个节点,也就是需要进行下次翻转的开头
                dNext = next.getNext();
            } else {
                // 将当前的链表和已经反转的链表相连,这里处理的是只剩一位
                return curr;
            }
            // 翻转
            next.setNext(curr);
            // 记录已翻转的头结点
            pNext = next;
        }
        return pNext;
    }

    /**
     * 链表翻转2
     * 思路:创建一个新的链表,将原链表由头开始,一个个放入新链表即可,贼简单
     * @param node
     * @return
     */
    public static Node reverse2(Node node) {
        // 新链表表头
        Node newNodeHead = null;
        // 当前节点
        Node curr = node;
        // 下一个节点
        Node next = null;
        while (curr != null) {
            // 获取下一个节点
            next = curr.getNext();
            // 将当前节点放入新链表中
            curr.setNext(newNodeHead);
            // 重置new链表的表头
            newNodeHead = curr;
            // 下一位
            curr = next;
        }
        return newNodeHead;
    }

    /**
     * 链表翻转3
     * 思路:移位,如1->2->3->4->5
     * 第一次移位,变为2->1->3->4->5
     * 第二次移位,变为3->2->1->4->5
     * 以此类推,这个也是蛮简单的
     * @param node
     * @return
     */
    public static Node reverse3(Node node) {
        // 下一个节点
        Node next = node.getNext();
        // 头结点
        Node head = node;
        while (next != null) {
            // node一直指向开始的头结点,设置他的下一个节点
            node.setNext(next.getNext());
            // 将跳过的节点设置到表头
            next.setNext(head);
            // 重置表头
            head = next;
            // 下一位
            next = node.getNext();
        }
        return head;
    }

    /**
     * 根据步长翻转,这个方法的思路是根据步长截取每段,然后进行翻转,然后拼接.单向链表,这个写起来感觉很麻烦
     * @param node
     * @param step
     * @return
     */
    public static Node reverse(Node node, int step) {
        // 当前头结点,翻转之后的尾节点
        Node currHead = null;
        // 下一个头结点
        Node nextHead = node;
        // 当前结点,用于计算尾节点
        Node curr = null;
        // 上一个的尾节点
        Node pTail = null;
        // 这里设置为null是为了为node重新赋值
        node = null;
        while (nextHead != null) {
            // 存储上步的尾节点,为下面使用
            pTail = currHead;
            curr = currHead = nextHead;
            // 根据步长找到尾节点
            for (int i = 0; i < step - 1; i++) {
                if (curr.getNext() != null) {
                    curr = curr.getNext();
                }
            }
            // 记录下一个步长开始位置
            nextHead = curr.getNext();
            // 将当前节点独立出来进行翻转
            curr.setNext(null);
            // 链表翻转,这里没用接收结果是因为,翻转完之后头变尾,尾变头
            reverse(currHead);
            if (pTail != null) {
                // 由于单链表翻转丢失前端节点,所以这里在翻转完成之后再进行链表的连接
                pTail.setNext(curr);
            }
            // 这里从新设定表头
            if (node == null) {
                node = curr;
            }
        }
        return node;
    }

}

你可能感兴趣的:(链表翻转,单向链表,(根据步长翻转))