数据结构——(PTA)02-线性结构3 Reversing Linked List

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.

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

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:

输入规格:
每个输入文件包含一个测试用例。对于每一种情况,第一行包含第一个节点的地址,一个正的N(≤105)是节点的总数,一个正的K(≤N)是要反转的子列表的长度。节点地址为5位非负整数,NULL用-1表示。
接下来是N行,每一行描述一个节点,格式如下:

Address Data Next

where Address is the position of the node, Data is an integer, and Next is the position of the next node.

其中Address是节点的位置,Data是一个整数,Next是下一个节点的位置

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

代码长度限制

16 KB

时间限制

400 ms

内存限制

64 MB

这道题大概意思就是,读入三个数字first、N、K,然后读入一个链表,首地址是first,长度N;读入顺序非结点顺序 ,读入数据中的address为本结点地址,next为下一个结点地址。要求:将该链表按照K个结点为一段,分别逆序;剩余结点不足K个,顺序输出。

这道题是曾经微软的一道面试题,由陈姥姥改造后,测试样例中加入了无用结点。也就导致排序逆序输出的同学挂了。(陈姥姥威武)。

解题思路一(测试样例5未通过,最大N运行时间过长,不推荐):

1、建立一个长度为N的结构数组,读入N个结点的数据,并通过address和next将各结点排序,数组第一个元素是地址为first的结点,第二个为first的next,以此类推。可通过address和next的指向将无用结点排除掉,同时数组长度len--。

2、将排好序的数组,按照每K个进行翻转,也就是0和k-1互换,1和k-2互换直至两个下标相等或者重叠,注意len为奇数时,最后一次互换的下标相差2,偶数时下标相邻。

3、遍历数组输出。

代码如下:

#include 
#include 
typedef struct node{
	int fadress;
	int data;
	int nadress;
}Node;
int N,K;									//声明全局变量 N为链表长度,K为逆序长度 

Node **read();								//读取函数 ,返回结构数组地址 
int search(Node *array[],int k,int index);	//搜索函数,index传入搜索开始的下标,返回目标结点下标 

Node **reverse(Node **array);				//翻转函数 

void print(Node **array);					//打印函数 

int main(int argc,char const *argv[]){
	Node **array=read();
	print(array);
	array=reverse(array);
	print(array);
	return 0;
}

int search(Node *array[],int k,int index){      
    int res=-1;
	for(int i=index;ifadress){
			res=i;
		}
	}
    return res;
}
Node **read(){
	int first;
	scanf("%d%d%d",&first,&N,&K);
	Node **array=(Node**)malloc(sizeof(Node*)*N);	//创建结构指针数组,元素为结构体指针 
	FILE *fp=fopen("test.txt","r");					//用文件读入数据,方便自己测试 
	int head=0;
	for(int i=0;ifadress,&array[i]->data,&array[i]->nadress);
		if(array[i]->fadress==first) head=i;		//记录头结点的下标 
	}
	fclose(fp);
	Node *ptemp=array[head];						//将头结点放在下标为0的位置 
	array[head]=array[0];array[0]=ptemp;
	
	for(int i=1;inadress,i);//i以前已排好序,从i向后搜索(i-1)的next 
		if(temp!=-1){								 
			array[i]=array[temp];
			array[temp]=ptemp;
		}else{										//返回-1说明下标i-1位置结点为链表尾部,结点数为i 
			N=i;									//N=i,数组N缩短,去除无效下标。 
		}
	}
	return array;
}
void print(Node **array){
	for(int i=0;ifadress,array[i]->data);
		if(array[i]->nadress!=-1) printf("%-.5d\n",array[i]->nadress);
		else printf("%d\n",array[i]->nadress);
	}
}

Node **reverse(Node **array){
	int i,j;
	int cnt=N/K;							//数组N里面有cnt个K,也就是分cnt段翻转;i为段首,j为段末 
	for(i=0,j=i+K-1;i0) array[i-1]->nadress=array[i]->fadress;//对调后,如果不是第一个元素,需要将next地址链接起来 
	}
	if(cnt*K!=N) array[cnt*K-1]->nadress=array[cnt*K]->fadress;//cnt*K!=N,有剩余结点需链接上。 
	array[N-1]->nadress=-1;					//将数组最后一个元素的next设为-1,为链表尾。 
	return array;
}

解题思路二(使用链表实现,将链表逐段翻转):

1、创建一个长度为最大N的结构指针数组array[MAXN]也就是长度为10e5,读入每个结点,地址为数组下标,next指向下一个结点的下标。创建Node *plist=array[first];利用下标将每个结点链接起来,array[i]=array[array[i]->naddress]。

2、先实现一个段的翻转。利用三个指针分别指向链表的首New、第二个old、第三个ptemp结点。

p=plist,临时保存首结点。old->next=New;New=old;old=ptemp,循环K次,p->next=old;完成一次K个结点的翻转,并链接到后续结点。

3、将整个链表需要翻转的结点分为cnt段,cnt=N/K。循环cnt次,将每段翻转。

代码如下:

#include 
#include 
typedef struct node Node;
typedef int ElementType;
struct node{
	int index;
	ElementType data;
	int nadress;
	Node *next;
};
#define MAX 100001
int n;										//声明全局变量n 
Node *read(int first);						//读入函数 
Node *reverse(Node *plist,int k);			//逆序函数,返回逆序后的头结点地址 
void print(Node *plist);					//打印函数 
int main(int argc,char const *argv[]){
	int first,k;
	scanf("%d%d%d",&first,&n,&k);
	Node *plist=read(first);
	
	int cnt=n/k;							//链表内有cnt个K, 
	Node *ptemp=plist,*p=plist;				//ptemp指向当前段的段首
/*此循环如果被放在reverse函数内,运行超时*/
	for(int i=0;inext=ptemp;p->nadress=ptemp->index;//将处理后的段,链接到上个段的末尾 
			p=q;							//将p指向当前段的段尾 
		}
		ptemp=p->next;						//ptemp指向下个段首 
	}
	print(plist);
	return 0;
}
Node *read(int first){
	Node *array[MAX];						//设置长度为MAX的结构指针数组 
	Node *plist=NULL;						//定义链表头指针 
//	FILE *pf=fopen("test.txt","r");			//从文件读取数据,方便自己测试,可删除 
	for(int i=0;idata,&array[index]->nadress);
		array[index]->index=index;
		if(index==first) plist=array[index];
	}
//	fclose(pf);
	Node *p=plist;	//下面循环是利用结构体内内部index和nadress将链表链接起来 
	for(p=plist,n=1;p->nadress!=-1;p->next=array[p->nadress],p=p->next,n++);
	p->next=NULL;	//此时p是链表末尾结点,n是链表中有效结点数量。 
	return plist;
}
Node *reverse(Node *plist,int k){
	Node *p=plist,*ptemp=NULL;
	Node *New=plist,*old=New->next;
	while(k>1){
		ptemp=old->next;			//New为链表头,old为第二个结点,ptemp为第三个结点 
		old->next=New;				//old指向New,new,old,和ptemp逐一向后移 
		old->nadress=New->index;	//k控制向后移动的距离 
		New=old,old=ptemp;
		k--;
	}
	p->next=old;					//记录逆序前的首结点,逆序完成后变为末结点,指向后续结点 
	
	if(old){
		p->nadress=old->index;		//后续结点为不为空时,更新p的nadress 
	}else{
		p->nadress=-1;				//后续结点为空时,p为链表的末结点,p的nadress设为-1; 
	}
	return New;						//函数返回逆序后,段的头结点。 
}
void print(Node *plist){
	for(Node *p=plist;p;p=p->next){
		printf("%.5d %d ",p->index,p->data,p->nadress);
		if(p->nadress!=-1) printf("%.5d\n",p->nadress);
		else printf("%d\n",p->nadress);
	}
}
/*将分段的循环放入reverse函数内部,测试数据最大N运行超时
Node *reverse(Node *plist){
	Node *p=plist,*ptemp=NULL;
	Node *New=plist,*old=New->next;
	for(int i=0;i1){
			ptemp=old->next;
			old->next=New;
			old->nadress=New->index;
			New=old;old=ptemp;
			j--;
		}
		if(i==0){
			plist=New;
			p->next=old;
			if(old){
				p->nadress=old->index;
				New=old;old=New->next;
			}else{
				p->nadress=-1;
			}
		}else{
			p->next=New;p->nadress=New->index;
			if(old){
				New=old;old=New->next;
			}else{
				q->next=NULL;
				q->nadress=-1;
			}
			p=q;
		}
	}
	return plist;
}*/

你可能感兴趣的:(数据结构)