单链表分段翻转【数据结构】手绘图快速理解

该题最初看到是在陈越老师的数据结构习题中看到

手把手教会你这到题==。==不管是啥语言都能看懂,我这里用的是java

我的手绘图被我弄丢了,过两天有时间补上,先发一下思路

|我先放一个用java提供的linkedList快速实现的方法,如果是快速完成作业的小伙伴可以用这个
// 可见linkedList多么方便

public class Exe3_2_2 {
    public static void main(String[] args) {

        LinkedList linkedList = new LinkedList();
        Scanner scanner = new Scanner(System.in);
//        创建链表
        linkedList.add(123);
        linkedList.add(1);
        linkedList.add(3);
        linkedList.add(12);
        linkedList.add(1);
        linkedList.add(2);
        linkedList.add(3);

//        ListIterator listIterator = linkedList.listIterator(3);
//        System.out.println(listIterator);
//        System.out.println("------------------");
//        记录未翻转的位数
        int size = linkedList.size();
        System.out.print("翻转的位数:");
//        当前翻转的位置
        int startPosition = 0;
        int K = scanner.nextInt();
        for (; size>=K ; size-=K) {
            Collections.reverse(linkedList.subList(startPosition,K + startPosition));
//            移动下一次开始翻转的位置
            startPosition +=K;
        }
        System.out.println(linkedList);


    }

}

接下来进入正题

题目:
给定的带头节点的单链表,K是每段的长度,将链表的每K位翻转
要点:末尾不足K位不翻转

例:
链表 1 2 3 4 5 6 7 8
输入 每几位翻转: 3
输出 3 2 1 6 5 4 7 8

为了方便大家观察我就把原来的链表安顺序写成了 1 2 3 4 5 6 7 8

还是先定义一个结点类,不赘述了,这个地方有问题的可以看我的单链表翻转

Node 类

public
class Node {
    private int Data;// 数据域
    private Node Next;// 指针域

    public Node(){

    };
    public Node(int Data) {
        // super();
        this.Data = Data;
    }

    public int getData() {
        return Data;
    }

    public void setData(int Data) {
        this.Data = Data;
    }

    public Node getNext() {
        return Next;
    }

    public void setNext(Node Next) {

        this.Next = Next;
    }
    public int length(Node head){
        int count = 0;
        while (head.getNext()!=null){
            count++;
            head = head.getNext();
        }
        return count;
    }
}

主方法

  1. 代码并不难理解,抛去输入输出,结点创建,链接,关键要看的只有几行
  2. 算法的核心在于定义的三个Node变量 current next tmp
  3. 这里我用了头节点head需要注意,Reverse函数每次被调用时都是传入的头节点和翻转的位数

看我手绘的图来快速帮你理解,直接从开始调用Reverse开始

1.首先判断如果是按每一位翻转即为不翻转直接退出

//        如果每一位翻转,即不翻转直接返回
    if (K == 1){
        return head;
    }

2.此时链表的结构是这样的,注意头节点

public class Exe3_2_2Node {
    public static void main(String[] args) {
        Exe3_2_2Node exe= new Exe3_2_2Node();
        Scanner scanner = new Scanner(System.in);


//        创建节点
        Node node1 = new Node(1);
        Node node2 = new Node(2);
        Node node3 = new Node(3);
        Node node4 = new Node(4);
        Node node5 = new Node(5);
        Node node6 = new Node(6);
        Node node7 = new Node(7);
        Node node8 = new Node(8);

//        设置头节点
        Node head = new Node();
        head.setNext(node1);

//        形成链表
        node1.setNext(node2);
        node2.setNext(node3);
        node3.setNext(node4);
        node4.setNext(node5);
        node5.setNext(node6);
        node6.setNext(node7);
        node7.setNext(node8);
//        链表的长度
        int length = head.length(head);
        System.out.println(length);
        System.out.print("输入每几位翻转");
        int K = scanner.nextInt();

        Node h = head;
//        判断翻转的次数

        Node nonReverseHead = head;
        for (int i = 1; i <= length/K ; i++) {
            nonReverseHead = exe.Reverse(nonReverseHead,K);
        }


        while (h.getNext()!=null){
            System.out.println(h.getNext().getData());
            h = h.getNext();
        }

    }

public  Node Reverse(Node head,int K){

//        如果每一位翻转,即不翻转直接返回
    if (K == 1){
        return head;
    }
//    创建三个判断位置

    Node current = head.getNext();
    Node next = current.getNext();
    Node tmp = next.getNext();
    Node nonReverseHead = current;


    for (int count = 1; count <K ; count++) {
//        翻转
        next.setNext(current);
//        将current next tmp顺次后移
        current = next;
        next = tmp;

        if (tmp != null){
            tmp = tmp.getNext();
        }

    }

//    移动head指向的位置以及head后第一个元素的指向的位置,即重新链接链表
        head.getNext().setNext(next);
        head.setNext(current);
        return nonReverseHead;
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值