02-线性结构3 Reversing Linked List(25 分)
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.
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.
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.
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
分析:这道题很有意思,题目要求给定一个链表,长度N,需要反向输出的长度K,就是说对一个链表实现循环前K个反向输出, 直到输出长度小于K。例子: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。我的算法设计是:首先设计单向链表的反向输出函数,返回首地址。然后定义数组来存储这些不同段的首地址,最后将这些段连接起来。算法复杂度O(N)。
如果只是这样的话,这道题也不能算难。但是仔细看输入输出要求:
1、输入的链表还需要重新按照给定的当前地址与下一个地址排序。我设计的算法是:首先找出在链表中找出给定的首地址。然后对当前结点指向地址与后面结点的当前地址进行判断(遍历),如相等则与当前结点的下一个结点进行数据交换。算法复杂度大于O(N),但小于O(N^2).
2、输入的链表中有些是无效结点,需要剔除。我的思路是判断结点指向地址是否等于-1.
3、链表的逆序算法原理:
代码有些长,两百多行,可以只看函数实现部分,输入输出可以不看,欢迎互相探讨,谢谢!
#include
#include
#include
typedef struct LNode *List;
struct LNode{
char Address[6];
int Data;
char Next_Address[6];
List next;
};
void Gets(char a[]);
List ReadInput(int N);
void Print(List L);
List Reversing(List L, char First_Address[], int K, int N);
void LSord(List L, List P);
List Ni_Xu(List L,int K);
int main()
{
// while(getchar()!=EOF)
// {
List L,R;
/*
** 0Address);
scanf("%d",&P->Data);
getchar();
Gets(P->Next_Address);
t = P;
P = (List)malloc(sizeof(struct LNode));
t->next = P;
}
free(P);
t->next = NULL;
return L;
}
void Print(List L)
{
List P = L;
if(P == NULL) printf("NULL\n");
for( ; P != NULL; P = P->next)
printf("%s %d %s\n", P->Address, P->Data, P->Next_Address);
}
List Reversing(List L, char First_Address[], int K, int N)
{
List P,P1,t;
int i,cnt=1;
/*
** 将链表按地址排序
*/
for(P = L; P != NULL; P = P->next) /* 查找首地址,并放于头结点 测试:OK*/
{
if( strcmp( First_Address, P->Address) == 0 ) /* 交换头结点与查找结点的元素 */
{
LSord( L, P );
break;
}
}
for(P = L; P->next != NULL; P = P->next) /* 按地址重排 */
{
P1 = P->next;
for(; P1 != NULL; )
{
if( strcmp( P->Next_Address, P1->Address) != 0 )
P1 = P1->next;
else
{
LSord(P->next,P1);
break;
}
}
}
for( P = L; strcmp(P->Next_Address,"-1") != 0 ; P = P->next) /* cnt 实际有效结点数 */
cnt++;
P->next = NULL;
// Print(L);
P = L;
int len;
if( cnt % K == 0) len = cnt/K;
else len = cnt/K +1;
List R[len]; /* 分段保存逆序后的链表 */
for(i = 0; P != NULL && (i+1)*K <= cnt; i++) /* 变换前K个元素顺序 */
{
List f0 = P;
int j;
for(j = 0; j < K; j++)
P = P->next;
R[i] = Ni_Xu(f0,K);
}
if( cnt % K != 0) /* 为变换的段 */
R[i] = P;
else /* 后面指向NULL */
{
P = R[i-1];
int j;
for(j = 1; j < K; j++)
P = P->next;
P->next = NULL;
}
for(i=0; inext;
P->next = R[i+1];
}
P = R[0]; /* 此时下一个结点的地址需要重新修改 */
for( ;P->next != NULL; P = P->next)
strcpy(P->Next_Address,P->next->Address);
P->Next_Address[0] = '-'; /* 最后一个结点下一个地址为-1 */
P->Next_Address[1] = '1';
P->Next_Address[2] = '\0';
// Print(R[0]);
// printf("test4\n");
return R[0];
}
/*
** 交换L,P中元素
*/
void LSord(List L, List P)
{
char s1[6],s2[6];
int d;
strcpy(s1, L->Address);
strcpy(s2, L->Next_Address);
d = L->Data;
strcpy(L->Address, P->Address);
strcpy(L->Next_Address, P->Next_Address);
L->Data = P->Data;
strcpy(P->Address, s1);
strcpy(P->Next_Address, s2);
P->Data = d;
}
List Ni_Xu(List L,int K)
{
List P0,P,t;
int i;
P0 = L;
P = P0->next;
for( i = 1; P != NULL && i < K; i++ )
{
t = P->next;
P->next = P0;
P0 = P;
P = t;
}
return P0;
}
void Gets(char a[])
{
int i;
for(i=0;;i++)
{
a[i]=getchar();
if(a[i] == ' ' || a[i] == '\n') break;
}
a[i] = '\0';
}