该题最初看到是在陈越老师的数据结构习题中看到
手把手教会你这到题==。==不管是啥语言都能看懂,我这里用的是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;
}
}
主方法
- 代码并不难理解,抛去输入输出,结点创建,链接,关键要看的只有几行
- 算法的核心在于定义的三个Node变量 current next tmp
- 这里我用了头节点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;
}
}