【PAT B1025】反转链表 (C语言)

我喜欢事实。
在这里插入图片描述
做为一个菜鸟,我用两个数组实现,第一个数组的下标就是该结点的地址,里面再存数据和下一结点的地址。用另外一个数组反向存储,即数组下标存储地址,里面存储的信息是它上一个结点的地址。剩下的就是慢慢找够K个反向输出,找输出。
下面是粗糙的代码。

#include <stdio.h>
#define MAX_N	100001
typedef struct node{
	int address;
	int data;
	int next;
}node;
typedef struct F_node{
	int data;
	int next;
}F_node;
struct F_node F_N[MAX_N];			/* 数组下标为address 它的下一个结点为next */
int R_N[MAX_N];						/* 数组下标为next,它存储的值为address, 即下标的上一个结点 */
int first_a;						/* 首地址 */
int K;								/* 每K个节点翻转 */
int read_N();
int print_N();
int print_K_node(int i);
int print_remain_node(int i, int j);
int print_num(int x);
/********************************** 读取输入的数据 *********************************/
int read_N(){
	int i, N;
	struct node p;

	scanf("%d %d %d", &first_a, &N, &K);
	for(i = 0; i < N; ++i){
		scanf("%d %d %d", &p.address, &p.data, &p.next);
		F_N[p.address].data = p.data;
		F_N[p.address].next = p.next;
		R_N[p.next] = p.address;
	}
}
/********************************* 输出数据 ****************************************/
int print_N(){
	int i, j;

	i = first_a;					/* 从第一个地址开始 */
	while(1){
		for(j = 1; j < K; ++j){		/* 找够K个结点 */				
			if(F_N[i].next != -1)				
				i = F_N[i].next;
			else				
				break;
		}
		if(j == K){					/* 如果找到了一组 */
			print_K_node(i);		/* 输出一组结点 */
			if(F_N[i].next == -1)	/* 后面再没有结点了 */
				break;				/* 结束 */ 
		}
		else{						/* 如果没有找够一组,i是最后一个结点的地址, 总共还有j个没输出 */
			print_remain_node(i, j);/* 按原来的顺序输出最后j个结点 */
			break;					/* 结束 */
		}
		i = F_N[i].next;			/* */
	}
}
/*********************** 反向输出第一个结点地址为i的K个结点 *************************/
int print_K_node(int i){
	int pos, j, n;

	for(pos = i, j = 0; j < K; ++j ){
		if(j < K-1){						/* 先输出本组K-1个结点 */
			print_num(pos);					/* 先把自己的地址输出去 */
			printf(" %d ", F_N[pos].data);	/* 输出数据 */
			print_num(R_N[pos]);			/* 输出pos的前一个结点地址 */
			pos = R_N[pos];					/* pos定位到前一个结点,准备下一次的输出 */
		}else{								/* 这是输出本组最后一个结点的时候 */
			print_num(pos);
			printf(" %d ", F_N[pos].data);
			if(F_N[i].next != -1){			/* 如果本组第一个输出的结点后面还有结点 */
				pos = F_N[i].next;			/* 寻找下一K组结点的第一个地址 */
				for(n = 1; n < K; ++n){
					if(F_N[pos].next != -1)
						pos = F_N[pos].next;
					else
						break;
				}
				if(n == K)					/* 找到了 */
					print_num(pos);
				else						/* 没有找到 */
					print_num(F_N[i].next);	
			}else							/* 若本组结点后面再无结点 */
				printf("-1");
		}
		printf("\n");
	}
	return 0;
}
/**************** 按原来的输出输出剩余的j个结点,最后一个结点地址为i ****************/
int print_remain_node(int i, int j){
	
	for(; j > 1; --j)					/* 先退回到剩余结点的第一个结点地址 */
		i = R_N[i];
	while(i != -1){
		print_num(i);					/* 输出地址 */
		printf(" %d ", F_N[i].data);	/* 输出数据 */
		if(F_N[i].next != -1)			/* 若它的下一个结点不为-1 */
			print_num(F_N[i].next);		/* 输出下一个结点的笛子 */
		else							/* 若为最后一个结点的地址 */
			printf("-1");				/* 结束 */
		i = F_N[i].next;
		printf("\n");
	}
	return 0;
}
/************************************* 输出x *****************************************/
int print_num(int x){
	int i, j;

	if(x < 10000){
		for(i = 0, j = 10000; i < 5; ++i, j /= 10){
			printf("%d", x / j);
			x = x % j;
		}
	}else
		printf("%d", x);
	return 0;
}
int main(){
	read_N();
	print_N();
	return 0;
}

/******************* 日记 ***************************/
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值