PAT 1025反转链表的代码实现及错误分析(C语言)

题目

给定一个常数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

注意陷阱:输入可能存在非链表内数据,需要剔除,最后一定是NULL

实现思路1:

1.定义结构体,包含3个整数(5位地址最后可加0输出),定义两个指定大小结构体数组link1和link2;

2.将数据存入数组link1,利用下个地址变量next将链表按顺序存入link2,同时计算数量也剔除了无效数据;

3.判断总数和块大小的关系,将反转之后的链表存入link1;

4.输出

代码如下:

#include

//定义结构体
typedef struct{
  int iAddr;
  int iData;
  int iNext;
} LINK;

int main()
{
  int next=0,iL=0,iK=0;
  scanf("%d%d%d",&next,&iL,&iK);
  LINK link1[iL+1],link2[iL+1];
  int iCnt=0;
  //存入数据到link1 
  for(int i=0;i0;i--)
    {
      for(int j=0;j0;i--)
    {
      for(int j=0;j

实现思路2:考虑地址是五位数,可建立大小为100000的数组,在第一遍存数据的时候,就把地址作为下标存入这个数组中。一切输入都存储完毕后,根据初始地址,一个一个在地址数组中查找对应的值(数组按下标查找比数组循环遍历效率高太多),并将其存入结构体数组中(结构体有三个变量:address,data,next),最后使用思路1翻转,输出结构体数组。

代码如下:

#include

struct node
{
    int add,data,next;
}a[100010],b[100010],c[100010];//a按地址下标存放输入数据,b依次存放顺序链表,c 
 
int main()
{
    int beginadd=0,n=0,k=0;
    int i=0,j=0,index=0;
    scanf("%d%d%d",&beginadd,&n,&k);
    //按地址下标存放输入数据 
    for(i = 0;i < n;i++)
    {
        scanf("%d",&index);
        scanf("%d %d",&a[index].data,&a[index].next);
    }
    //依次存放顺序链表 
    int num=0 
    for(i = beginadd;i != -1;i = a[i].next)
    {
        b[num].add = i;
        b[num].data = a[i].data;
        b[num].next = a[i].next;
        num++;
    }
    int s=num/k,y= num%k;//s为反转块数量,y为不反转链表节点数量 
    //按需反转,无需考虑next地址,因为顺序正确,next地址就是下一个节点的add 
	int pos = 0;
    for(i = 1;i <= s;i++)
    {
        for(j = i*k-1;j >= (i-1)*k;j--)
        {
            c[pos].add = b[j].add;
			c[pos].data = b[j].data;
			pos++;
        }
    }
    if(y != 0)
    {
        for(i = s*k;i < num;i++)
        {
            c[pos].add = b[i].add;
			c[pos].data = b[i].data;
			pos++;
        }
    }
 
	for(int k= 0; k < pos - 1; k++) {
		printf("%05d %d %05d\n", c[k].add, c[k].data, c[k+1].add);
	}
	printf("%05d %d -1\n", c[pos-1].add, c[pos-1].data);
    return 0;
}

错误分析:在一开始的思考中,如果把地址作为字符数组,则难度飙升,思路1的实现中,有测试点显示运行超时,思路2比思路1好的地方在于空间换时间,虽然开辟内存比较大, 但是省却第一次遍历排序链表,同时利用排好序的链表节点关系,直接忽略掉结构体中的next元素,将链表反转即可输出相关地址。

你可能感兴趣的:(PAT 1025反转链表的代码实现及错误分析(C语言))