C语言 02-线性结构3 Reversing Linked List (25 分)

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); 
} 
  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值