02-线性结构3 Reversing Linked List (25 分)
mooc数据结构网课上的作业题,大概说下题目要求:
先输入三个参数
(首地址address 结点个数N 需逆转序列长度k)
然后输入N个格式为(当前地址 数据值 下个地址 )的序列。
最后输出:完成逆转后的序列。
比如输入N=6,k=4 如下
则输入序列的连接顺序是 1-2-3-4-5-6
逆转后的序列是 4-3-2-1-5-6
主要思路:
用长为100001的数组a接收输入,根据元素的链接顺序把他们装入数组b(b的长为N,并非100001)。每个元素中都有一个nextIndex,代表着其后继元素在数组b中的下标。
逆转函数中只对元素的nextIndex值改变。
ps:之前用链表写过一遍,结果第5个测试点总是超时(估计是太多次遍历的原因),所以改用数组。
以下是代码:
#include<stdio.h>
typedef struct unit Data;
struct unit{
int address;//地址
int data;//数据
int nextAddress;//后续元素地址
int nextIndex;//后续元素在数组中的下标
};
int reverse(Data b[],int legal,int k){//反转函数
int i,j;
int tail,ptr1,ptr2;//tail是每次逆转后的末尾的下标值
int head;
int firstTime=0;//判别是否第一次处理
ptr1=0;
ptr2=1;
if(k==1||legal==1)
return -1;
else{
for(i=0;i<legal/k;i++){// 长度为k的序列个数
for(j=0;j<k-1;j++){//逆转 后面元素指向前面元素 下标递增
b[ptr2].nextIndex=ptr1;
ptr1++;
ptr2++;
}
firstTime++;
if(firstTime==1){//若是第一次处理 记下首地址 记下末尾元素的下标
head=ptr1;
tail=0;
}
else{//若非第一次处理 则使上一次处理的末尾指向此次逆序后的首元素 更新末尾元素下标
b[tail].nextIndex=ptr1;
tail+=k;
}
if(i+1>=legal/k)//若无下次循环即剩下元素无需处理 末尾直接指向剩余元素 否则 更新下标
b[tail].nextIndex=ptr2;
else{
ptr1++;
ptr2++;
}
}
}
return head;
}
void adjust(Data b[],int legal,int head){//给逆转后的数据调整nextAddress的值
int i;
for(i=0;i<legal;i++){
if(i+1<legal){
b[head].nextAddress=b[b[head].nextIndex].address;
head=b[head].nextIndex;
}
else
b[head].nextAddress=-1;
}
}
void output(Data b[],int legal,int head){//输出
int i=0;
if(head==-1){//元素或需逆转的个数只有1个的情况 直接输出
for(i=0;i<legal;i++){
if(b[i].nextAddress==-1)
printf("%05d %d %d",b[i].address,b[i].data,b[i].nextAddress);
else
printf("%05d %d %05d\n",b[i].address,b[i].data,b[i].nextAddress);
}
}
else{
for(i=0;i<legal;i++){
if(b[head].nextAddress==-1)
printf("%05d %d %d",b[head].address,b[head].data,b[head].nextAddress);
else
printf("%05d %d %05d\n",b[head].address,b[head].data,b[head].nextAddress);
head=b[head].nextIndex;
}
}
}
void main(){
Data a[100001];//存放输入数据的数组 用下标和地址匹配进行存放
Data temp;
int FirstAddress,N,k; //首地址 元素个数 需逆转个数
int head
int i,legal; //legal是有效元素个数
scanf("%d %d %d",&FirstAddress,&N,&k);
Data b[N];// b数组的大小为N,将按序存放各个元素
for(i=0;i<N;i++){ //输入元素到数组 a
scanf("%d %d %d",&temp.address,&temp.data,&temp.nextAddress);
a[temp.address]=temp;
if(temp.address==FirstAddress)//首地址元素 作为数组b的首元素
b[0]=temp;
}
i=0;
while(b[i].nextAddress!=-1){//按地址顺序把 a 中元素装入 b 中,并赋值nextIndex使他们按序连在一起
b[i].nextIndex=i+1;
b[i+1]=a[b[i].nextAddress];
i++;
}
legal=i+1;//合法元素个数
head=reverse(b,legal,k);
if(head!=-1)
adjust(b,legal,head);
output(b,legal,head);
}