其实这篇文章在很久之前就应该发出了,但是当时在学校,上课之类的一系列事情耽误了,(最主要的是要陪别(dui)人(xiang),嘿嘿)但是这个是我写文章的第一篇,所以不想放弃,就填个坑,当时的我觉得这道题巨难,做出来贼nb,(现在看来贼简单)所以开了一个头,写文章的时候从草稿堆里翻出来的,就写一下
同时,告诉大家,坚持,回头看做过的路会感觉之前走过的路特别简单!!!
题目
给定一个带头结点的单链表和一个整数K,要求你将链表中的每K个结点做一次逆转。例如给定单链表 1→2→3→4→5→6 和 K=3,你需要将链表改造成 3→2→1→6→5→4;如果 K=4,则应该得到 4→3→2→1→5→6。
函数接口定义
void K_Reverse( List L, int K );
其中 List结构定义如下:
typedef struct Node *PtrToNode;
struct Node {
ElementType Data; /* 存储结点数据 */
PtrToNode Next; /* 指向下一个结点的指针 */
};
typedef PtrToNode List; /* 定义单链表类型 */
L是给定的带头结点的单链表,K是每段的长度。函数K_Reverse应将L中的结点按要求分段逆转。
裁判测试程序样例:
#include <stdio.h>
#include <stdlib.h>
typedef int ElementType;
typedef struct Node *PtrToNode;
struct Node {
ElementType Data; /* 存储结点数据 */
PtrToNode Next; /* 指向下一个结点的指针 */
};
typedef PtrToNode List; /* 定义单链表类型 */
List ReadInput(); /* 裁判实现,细节不表 */
void PrintList( List L ); /* 裁判实现,细节不表 */
void K_Reverse( List L, int K );
int main()
{
List L;
int K;
L = ReadInput();
scanf("%d", &K);
K_Reverse( L, K );
PrintList( L );
return 0;
}
/* 你的代码将被嵌在这里 */
一、输入
6
1 2 3 4 5 6
4
二、输出
4 3 2 1 5 6
三、思路
对于此题,最基础的是链表逆置算法
而有所改进的是:
1.了解逆置规则
对于最后输入的数字n,需要每隔n个数字进行逆置,如果剩余的数字个数小于n,则不足的部分并再在进行逆置
2.了解逆置算法
在这里,博主给出大家链表逆置算法
大家可以吧它背住,考试或者做题默写上去,很方便快捷:
head=head->next;
plist bt1=NULL,p=head;
bt=head;
while(p){
p=p->next;
bt->next=bt1;
bt1=bt;
bt=p;
}
这是算法核心,基本思路是这样的:
用三个单元来完成,让第一个指向空(没有头指针),然后下面的一个指向第一个,这样一个一个逆置,最后 p 和 bt 都是空,bt1指向头
我写了一个完整的,大家可以运行一下试试:
#include<stdio.h>
#include<stdlib.h>
typedef struct list{
int data;
struct list *next;
}list,*plist;
int main(){
plist bt=(plist)malloc(sizeof(list));
int i;
plist head=bt;
for(i=0;i<10;i++){
plist bt1=(plist)malloc(sizeof(list));
bt1->data=i;
bt1->next=NULL;
bt->next=bt1;
bt=bt1;
}
head=head->next;
plist bt1=NULL,p=head;
bt=head;
while(p){
p=p->next;
bt->next=bt1;
bt1=bt;
bt=p;
}
while(bt1){
printf("%d ",bt1->data);
bt1=bt1->next;
}
}
这个小程序可以自动赋值,初始数据是
0 1 2 3 4 5 6 7 8 9
运行结果是
9 8 7 6 5 4 3 2 1 0
(博主运行过了,可以正常运行)
四、程序代码
void K_Reverse( List L, int K ){
List p1,p2,p3=NULL,n,p,c;
int q=0,i,d;
p=p1=L->Next;
while(p){
q++;
p=p->Next;
}
q=q/K;
if(q!=0){
n=p1;
for(i=0;i<K;i++){
p2=p1->Next;
p1->Next=p3;
p3=p1;
p1=p2;}
}
if(q!=0)
L->Next=p3;
for(d=0;d<q-1;d++){
p3=NULL;
c=p1;
for(i=0;i<K;i++){
p2=p1->Next;
p1->Next=p3;
p3=p1;
p1=p2;
}
n->Next=p3;
n=c;
}
if(q!=0)
n->Next=p1;
return L;
}
五、提交结果截图
总结
总的来说,首先得知道需要逆置几次,然后分段分进行逆置,最后如果还有剩余,就直接添加到链表末尾