Given a constant K and a singly linked list L, you are supposed to reverse the links of every K elements on L. For example, given L being 1→2→3→4→5→6, if K=3, then you must output 3→2→1→6→5→4; if K=4, you must output 4→3→2→1→5→6.
Input Specification:
Each input file contains one test case. For each case, the first line contains the address of the first node, a positive N (≤105) which is the total number of nodes, and a positive K (≤N) which is the length of the sublist to be reversed. The address of a node is a 5-digit nonnegative integer, and NULL is represented by -1.
Then N lines follow, each describes a node in the format:
Address Data Next
where Address
is the position of the node, Data
is an integer, and Next
is the position of the next node.
Output Specification:
For each case, output the resulting ordered linked list. Each node occupies a line, and is printed in the same format as in the input.
Sample Input:
00100 6 4
00000 4 99999
00100 1 12309
68237 6 -1
33218 3 00000
99999 5 68237
12309 2 33218
Sample Output:
00000 4 33218
33218 3 12309
12309 2 00100
00100 1 99999
99999 5 68237
68237 6 -1
小白第一次写数据结构的编程题,学校出的还是英文题,一下子给看懵逼了(完全看不懂)
题目分析:第一行输入了三个东西,分别是第一个地址、数据的总个数、反转数据的个数。
后面几行都是输入的数据:数据地址 数据大小 下一个数据的地址
反转在题目中详细说明了,比如说给定1→2→3→4→5→6,要按4来反转,就输出 4→3→2→1→5→6.
代码分析:因为输入数据中每一行的下一个数据地址和下一行的数据地址不一样,所以我们先得给输入的数据排序,按给定的地址来排,使它们成为1→2→3→4→5→6的形式,之后去除多余的节点(这点也是看大佬的做法http://t.csdn.cn/TPJL0),把剩余的几个数据进行翻转,进而输出。
主函数
#include<stdio.h>
#include<stdlib.h>
#define Max 100000
typedef struct {//题目要求的线性表要包含的三个地址
int Address[Max];//当前地址
int Data[Max];//数据
int Next[Max];//下一个地址
}Lnode, *Linkedlist;
void sort(Linkedlist L, int N,int firstaddress);//排序
void change(Linkedlist L, int i, int j);//交换数据
int check(Linkedlist L, int n); //检查数组长度
void reverse(Linkedlist L, int N, int K);//反转链表
int main()
{
int firstaddress,N,K;
int i=0;
scanf("%d%d%d",&firstaddress, &N, &K);
Linkedlist L;
L = (Linkedlist)malloc(sizeof(Lnode));//使用malloc函数生成头结点
for (i = 0; i < N; i++)
{
scanf("%d%d%d", &L->Address[i], &L->Data[i], &L->Next[i]);
}
sort(L,N,firstaddress);
N = check(L, N);//取得新数组的长度
reverse(L, N, K);
for (int i = 0; i<N-1; i++)
{
printf("%05d %d %05d\n", L->Address[i], L->Data[i], L->Next[i]);
}//因为地址以零开头,使用05d补全
printf("%05d %d %d", L->Address[N - 1], L->Data[N - 1], L->Next[N - 1]);
return 0;
}
排序函数、交换函数
排序的思想很简单,就是根据地址的关系,将地址(靠前的)小的提到前面,地址等于首地址的放在最前面,大的放在后面直到遍历完这个线性表。
交换函数使用了临时变量t1、t2、t3,来完成两个数据的交换,
void sort(Linkedlist L, int N, int firstaddress)
{
int i, j;
for (i = 0; i < N; i++)
{
for (j = i; j < N; j++)
{
if (L->Address[j] == firstaddress)
{
change(L, i, j);
firstaddress = L->Next[i];
break;
}
}
}
}
void change(Linkedlist L, int i, int j)//两个数据交换函数
{
int t1, t2, t3;
t1 = L->Address[i];
t2 = L->Data[i];
t3 = L->Next[i];
L->Address[i] = L->Address[j];
L->Data[i] = L->Data[j];
L->Next[i] = L->Next[j];
L->Address[j] = t1;
L->Data[j] = t2;
L->Next[j] = t3;
}
检查函数
我们遍历线性表,如果遇到一个数据的下一个地址是-1,这时候就要停止,然后输出有用数据的数量。(这个步骤是我自己写的时候没有想到的,但是看了很多人写的题解之后我发现之一步骤不可或缺,但是我没有get到它的意思,等之后再来填坑吧)。
int check(Linkedlist L, int n)
{
int i = 0;
while (L->Next[i]!= -1)
i++;
i++;
return i;
}
反转函数
首先K是反转的依据,每K个数反转一次,所以当开始 反转的位置+K 大于总长度N时,停止反转循环。
K/2表示反转的次数,长度为奇数,最中间的数不用动,所以num2/2向下取整就能解决这个问题。两个数交换位置就用到之前的交换函数。
之后更改下一个地址位置,用一个循环依此修改就可以了,最后一个数据的下一个地址改为-1
void reverse(Linkedlist L, int N,int K)
{
int i, j = 0;
while (j + K <= N)
{
for (i = 0; i < K / 2; i++)
{
change(L, i + j, j + K - i - 1);
}
j += K;
}
for (i = 0; i < N - 1; i++)//N-1是要对最后一个数据的下一个数据地址做修改
{
L->Next[i] = L->Address[i + 1];
}
L->Next[N - 1] = -1;//最后一个数据的下一个地址置空
}