Given a constant K and a singly linked list L, you are supposed to reverse the links of every K elements on L. For example, given L being 1→2→3→4→5→6, if K=3, then you must output 3→2→1→6→5→4; if K=4, you must output 4→3→2→1→5→6.
Input Specification:
Each input file contains one test case. For each case, the first line contains the address of the first node, a positive N (≤105) which is the total number of nodes, and a positive K (≤N) which is the length of the sublist to be reversed. The address of a node is a 5-digit nonnegative integer, and NULL is represented by -1.
Then N lines follow, each describes a node in the format:
Address Data Next
where Address
is the position of the node, Data
is an integer, and Next
is the position of the next node.
Output Specification:
For each case, output the resulting ordered linked list. Each node occupies a line, and is printed in the same format as in the input.
Sample Input:
00100 6 4
00000 4 99999
00100 1 12309
68237 6 -1
33218 3 00000
99999 5 68237
12309 2 33218
Sample Output:
00000 4 33218
33218 3 12309
12309 2 00100
00100 1 99999
99999 5 68237
68237 6 -1
![](https://img-blog.csdn.net/20160421170943415?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
题目思路:关键是单链表的逆转,这是陈越老师给的思路,但是还有些测试点没有通过,需要再思考
#include<stdio.h>
#include<stdlib.h>
#define MAXSIZE 100001 //100001=100000+1
typedef struct LNode *Ptr;
struct LNode{
int address;
int data;
int next;
Ptr link; //链表节点
}list;
Ptr Reverse(Ptr head, int K,int L);
Ptr MakeList(int f_add, int next_add[],int data[],int L);
void Attach(int a,int n_a,int data,Ptr *pRear);
void PrintList(Ptr P);
int main()
{
int K = 0, L = 0; //K是需要翻转的节点数,L是所有节点数
int link_num = 0;//链表节点数
int i;//用于计数
int address_tmp;//地址变量
int first_add;//首地址
Ptr p,p_tmp,r_p;
int Next[MAXSIZE] ;//用address当索引
int Data[MAXSIZE] ;//用address当索引
//读入首地址,数据数目,反转数目
scanf("%d %d %d",&first_add,&L,&K);
//读入数据建立数据存储空间
for(i = 0 ; i < L ; i++){
scanf("%d",&address_tmp);//读入地址
scanf("%d %d",&Data[address_tmp],&Next[address_tmp]);
}
//开始建立链表
p = MakeList(first_add,Next,Data,L);
//反转链表 ******************需要修改*****************************
if(K<=L){//K<=L才需要翻转
for(i = 0; i < (L/K); i++){
r_p = Reverse(p,K,L);
p_tmp ->link = r_p;//多次翻转的考虑
p_tmp ->next = r_p->address;
for(int j = 0; j < K; j++ ){
//使p指向下一段需要反转的子链表的头结点(第一个节点的前一个节点)
p_tmp = p_tmp->link;
}
}
}
//************************************************************
//输出链表
PrintList(p_tmp);
return 0;
}
Ptr MakeList(int f_add, int next_add[],int data[],int L)
{
Ptr P , Rear, t;
int t_L = L;
int a,n_a,d,tmp_n_a;
int i;
P = (Ptr)malloc(sizeof(struct LNode));//链表头空节点
P->link = NULL;
Rear = P;
//增加首节点
a = f_add;
d = data[a];
n_a = next_add[a];
Attach(a,n_a,d,&Rear);
t_L--;
while(t_L--){//其余节点增加
a = n_a;
d = data[a];
n_a = next_add[a];
Attach(a,n_a,d,&Rear);
}
//t = P;P=P->link;free(t);//删除临时生成头节点
return P;
}
void Attach(int a,int n_a,int data,Ptr *pRear)
{
Ptr P;
P = (Ptr)malloc(sizeof(struct LNode));
P->address = a;
P->data = data;
P->next = n_a;
P->link = NULL;
(*pRear)->link = P;
*pRear = P;
}
Ptr Reverse(Ptr head, int K,int L)
{
int cnt = 1;
Ptr new_, old,tmp;
//定义当前结点 new_,初始值为首元结点,new_ = head->link;
new_ = head->link;
//定义当前结点的后继结点 old, old = new_->link;
old = new_->link;
while(cnt < K){
//定义新节点 tmp,它是 old的后继结点,tmp = old->link;
tmp = old->link;
//把old的后继指向new_, old->link = new_;
old->link =new_;
//old的下一个地址是new_的地址
old->next = new_->address;
//此时,old 实际上已经到了 new_ 前一位成为新的new_,
//所以这个时候old 结点实际上成为新的 new_,new_ = old;
new_ = old;
//而新的 old 就是 tmp,old = tmp;
old = tmp;
cnt ++;
}
///使反转后的最后一个节点指向下一段子链表的第一个节点
head->link->link = old;
if(old != NULL){//对地址进行修改
head->link->next = old -> address;
}
else{
head->link->next = -1;//正好完全翻转的情况
}
return new_;
}
void PrintList(Ptr P)
{
while(P){
if(P->next == -1) {//对最后一个节点的单独处理
printf("%.5d %d %d\n",P->address,P->data,P->next);
}
else{
printf("%.5d %d %.5d\n",P->address,P->data,P->next);
//格式输出,%.5意味着如果一个整数不足5位,输出时前面补0 如:22,输出:00022
}
P = P->link;
}
}