题干描述
给定一个带头结点的单向链表,每个节点保存一个整数。请编写程序实现以下功能: 建立链表:从键盘输入若干整数,输入 0 表示结束(0 不加入链表)。 每次把新节点插入到链表尾部(保持输入顺序)。 反转链表前 K 个节点:给定一个整数 K,将链表前 K 个节点反转。 如果链表长度小于 K,则反转整个链表。 必须修改指针,不能只是改变输出顺序。 输出链表:输出链表中所有整数,每行一个。
输入格式
多行整数,每行一个整数,输入 0 表示结束。 一行整数 K,表示要反转的节点数量。
输出格式
每行一个整数,按链表实际顺序输出翻转后的结果。
输入样例 #1
3 8 5 10 7 0 3
输出样例 #1
5 8 3 10 7
输入样例 #2
5 0 1
输出样例 #2
5
输入样例 #3
1 2 3 4 5 0 6
输出样例 #3
5 4 3 2 1
核心题意理解
这道题的逻辑很简单,举一个例子:
原链表状态:head->3->8->5->10->7->NULL
当 K=3 时: 反转后链表是:head->5->8->3->10->7->NULL(前三个数据反转)
当 K=1 时: 反转后链表是:head->3->8->5->10->7->NULL(相当于没反转)
当 K=10 时: 反转后链表是:head->7->10->5->8->3->NULL(相当于整体反转)
具体实现方法
当然有原地反转链表的算法,但是它较为复杂,对于初学者难以理解,更别提自己写出来了。
这里重点介绍一种借助辅助链表的操作方法。
还是拿这个例子来说明: 原链表:head->3->8->5->10->7->NULL, k=3
第一步:定位
我们为了反转前三个节点,我们首先要用指针定位反转范围。为了方便操作,我们直接定位到第 4 个节点就好了。这里是实现这一操作对应的代码:
Node *nextAfterK=head->next;
while (nextAfterK!=NULL && k>0){
nextAfterK=nextAfterK->next;
k--;
}
并且这里天然解决了 K 大于链表长度的问题,因为这个指针会停在链表最后的 NULL 上。
第二步:利用辅助链表进行操作
我们借助一个辅助链表,把前 K 个节点使用头插法存入这个链表之中,这样前 K 个节点的顺序就自然反转过来了。
注意:新建链表时,头结点首先要进行动态内存申请,并进行初始化。
Node *dummy=(Node*)malloc(sizeof(Node));
dummy->next=NULL;
完整的举例过程:
原链表:head->3->8->5->10->7->NULL 辅助链表:dummy->NULL
-
把第一个节点从原链表中取出,插入新链表中。 原链表:head->8->5->10->7->NULL 辅助链表:dummy->3->NULL

