2018.7.8

PAT 1025 反转链表

1025 反转链表 (25)(25 分)

给定一个常数K以及一个单链表L,请编写程序将L中每K个结点反转。例如:给定L为1→2→3→4→5→6,K为3,则输出应该为3→2→1→6→5→4;如果K为4,则输出应该为4→3→2→1→5→6,即最后不到K个元素不反转。

输入格式:

每个输入包含1个测试用例。每个测试用例第1行给出第1个结点的地址、结点总个数正整数N(<= 10^5^)、以及正整数K(<=N),即要求反转的子链结点的个数。结点的地址是5位非负整数,NULL地址用-1表示。

接下来有N行,每行格式为:

Address Data Next

其中Address是结点地址,Data是该结点保存的整数数据,Next是下一结点的地址。

输出格式:

对每个测试用例,顺序输出反转后的链表,其上每个结点占一行,格式与输入相同。

输入样例:

00100 6 4
00000 4 99999
00100 1 12309
68237 6 -1
33218 3 00000
99999 5 68237
12309 2 33218

输出样例:

00000 4 33218
33218 3 12309
12309 2 00100
00100 1 99999
99999 5 68237
68237 6 -1

思路:

这题可以有两种想法。一是用纯链表写,但是比较麻烦的一点就是在逆转的时候不仅要考虑到内部链表方向的变化,还要考虑到这部分链表头尾的指针所指的对象;第二种是用结构数组写,也就是开一个数组,把输入的结构存到每个数组单元里,这样逆转链表的时候只需要做swap的动作就可以了,会方便直观很多。

主要涉及三个过程,初始化数组并读入数据;第一次链接,也就是把最开始读入的结构数组整理成“链表”的形式;逆转链表,一部分一部分地调换数组元素的位置。

第二个过程其实和选择排序比较类似;第三个过程最开始写的时候除了换位置,我还修改了每个结构的next值,后来发现其实不需要,因为这个点的next值其实就是下一个点的address值,只要在输出的时候换个对象就可以了。

另外还有一个比较坑的测试点,自己一直没有想到,参考了别人的博客才了解到。测试点中有一种情况:所给的所有节点中间有一个的next值为NULL,也就是说这个链表不是完整的N个节点的链表ORZ,被卡了好久。

代码:

#include<stdio.h>
struct node
{
	int address;
	int data;
	int next;
};
int main()
{
	int head, n, k;
	int i, j;
	scanf("%d %d %d", &head, &n, &k);

	struct node *temp;
	struct node **Node, **p;
	Node = (struct node**)malloc(sizeof(struct node)*n);
	for (i = 0; i < n; i++)
	{
		Node[i] = (struct node*)malloc(sizeof(struct node));
		scanf("%d %d %d", &Node[i]->address, &Node[i]->data, &Node[i]->next);
	}

	for (i = 0; i < n; i++)
	{
		for (j = i; j < n; j++)
		{
			if (i == 0 && Node[j]->address == head)
			{
				temp = Node[0];
				Node[0] = Node[j];
				Node[j] = temp;
				break;
			}
			if (i!=0 && Node[j]->address == Node[i - 1]->next)
			{
				temp = Node[j];
				Node[j] = Node[i];
				Node[i] = temp;
				break;
			}
		}
		if (Node[i]->next == -1)
		{
			n = i + 1;
		}
	}

	for (i = 0; i < n / k; i++)
	{
		p = Node + i * k;
		for (j = 0; j < k / 2; j++)
		{
			temp = p[j];
			p[j] = p[k - j - 1];
			p[k - j - 1] = temp;
		}
	}

	for (i = 0; i < n-1; i++)
	{
		printf("%05d %d %05d\n", Node[i]->address, Node[i]->data, Node[i+1]->address);
	}
	printf("%05d %d -1\n", Node[n-1]->address, Node[n-1]->data);

	for (i = 0; i < n; i++)
	{
		free(Node[i]);
	}
	free(Node);
	system("pause");
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值