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 (≤100000 ) 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
1.该题改编于微软的一道面试题,所以是英文。其大概意思是:给你一个广义上的链表,并给出以下数据:
第一行:首地址 节点数N 所需反转的节点数K
后N行:节点地址 节点所存数据 节点所指的下一节点地址
题目要求每K个反转一次;
e.g.
N=4;sentry->a->b->c->d //sentry为哨兵节点
(1).K=3 故得sentry->c->b->a->d;
(2).K=2故得sentry->b->a->d->c;
2.节点定义:
struct Node {
int val;
int next;
Node(){}
Node(int val_,int next_):val(val_),next(next_){}
};
我们选用结构数组模拟,不用链表(动态申请)的原因是:
(1).一般我们定义Node* p=new Node;便可以用"p->next"等进行对申请的节点操作,但是这里所给的地址是int型,若定义 int p=first_Address;不可以使用"p->next"等;
(2).所给N<100000;那我们开一个100000+1大小的结构数组,多出的“1”,作为哨兵节点(sentry).
3.链表类的申明:
class List{
private:
const int sentryAddr=100000;
//哨兵节点的下表为100000(常用),故用sentry代替之
struct Node array[100001];
//下表 0~100000 真正储存数据的节点下表为0~99999(100000个);
public:
List(int firAddr);
//构造函数中初始化一个哨兵节点(sentry)
void read(int addr,int val,int next);
//将每个节点接入
const void disPlay();
//按格式打印每个节点
int getLen();
//获得真实有用的链表长度(链表长度!=N)
void reverse(int K);//逆转链表的函数
};
4.格式化输出:
e.g.把 1 输出成 01;
#include <iostream> //引用相关输出头文件
#include <iomanip> //引用格式控制头文件
using namespace std ;
int main()
{
int a=1;
cout.setf(ios::right); //设置对齐方式为右对齐
cout.fill('0'); //设置填充方式,不足位补0
cout.width(2); //设置宽度为2,只对下条输出有用
cout<<a<<endl;
return 0;
}
5.总代码为:
#include <iostream>
#include <iomanip>
using namespace std;
struct Node {
int val;
int next;
Node(){}
Node(int val_,int next_):val(val_),next(next_){}
};
class List{
private:
const int sentryAddr=100000;
struct Node array[100001];
public:
List(int firAddr){
for(int i=0;i<=sentryAddr;++i)
array[i].next=-1;
array[sentryAddr].next=firAddr;
//初始化得一个哨兵节点
}
void read(int addr,int val,int next){
array[addr].val=val;
array[addr].next=next;
}
const void disPlay(){
int p=array[sentryAddr].next;
while(p!=-1){
cout.setf(ios::right);//网上查得输出格式
cout.fill('0');
cout.width(5);
cout<<p<<" "<<array[p].val<<" ";
if(array[p].next==-1){
cout<<"-1";//最后一行打印后无需再打印换行了
}else{
cout.setf(ios::right);
cout.fill('0');
cout.width(5);
cout<<array[p].next<<endl;
}
p=array[p].next;
}
}
int getLen(){
int p=array[sentryAddr].next;
int cnt=0;
while(p!=-1){
p=array[p].next;
cnt++;
}
return cnt;
}
void reverse(int K){
int cnt;
int head=array[sentryAddr].next;//至少一个节点
int link;//link保存逆转了的链表尾节点,保证后面的逆转衔接正常
if(K==1)
return;//故以下 节点数至少为2
int New,Old;
int len=getLen();
for(int i=0;i<len/K;++i){
New=head;
Old=array[New].next;
cnt=1;
while(cnt<K){
int Tmp=array[Old].next;
array[Old].next=New;
New=Old;
Old=Tmp;
cnt++;
}
array[head].next=Old;
/*
下面是为了保存链表的头
sentryAddr为哨兵得地址,固定值100000
head保存还未逆转的链表头
link保存逆转了的链表尾节点,保证后面的逆转衔接正常
*/
if(i==0)
array[sentryAddr].next=New;
else
array[link].next=New;
link=head;
head=Old;
}
}
};
int main()
{
int addr,next,N,K,val;
cin>>addr>>N>>K; //第一行 首地址 节点个数N K
List L(addr);
for(int i=0;i<N;++i){
cin>>addr>>val>>next;
L.read(addr,val,next);
}
L.reverse(K);
L.disPlay();
return 0;
}