(c语言)02-线性结构3 Reversing Linked List(包含讲解)

本实验取材于浙江大学《数据结构》.
在这里插入图片描述
听过姥姥讲的小白专场知道,这道题卡的是多余结点。姥姥讲的非常仔细,但是代码如何去写有是一个问题。拿到题目的时候惊慌了一下,努力坚持要写下去。
一个好的c语言包含了三样东西

  • 输入
  • 处理
  • 输出
    很显然这道题的难点在于处理,下面给出
#include<stdio.h>
#include<stdlib.h>
#define MAXLEN 100002
struct node{
	int data;
	int next;
}workArray[MAXLEN];
int k,head;//k是你需要反转的个数
struct node workArray[MAXLEN];//结构体数组
int Input(struct node array[]){
	int i,inputHead,inputLength;
	int index,data,next;
	scanf("%d %d %d",&inputHead,&inputLength,&k);
	for(i=0;i<inputLength;i++){
		scanf("%d %d %d",&index,&data,&next);
		array[index].data = data;
		array[index].next = next;
	}
	return inputHead;
}
//有什么感想呢?对这道题目的感想就是,你肯要有输入
//首先输入头结点 结点个数  想要逆转节点个数
//然后遍历 将输入第一个值变成数组的索引即index
//第二个值也就是4 3 2 1 那种data域里的值。
//第三个值就是下一个索引也就是你的吓一跳,把这些存入到数组里
//然后开始后续操作。
int count(int head,struct node array[]){
	int i,cnt = 1;
	i = head;
	while(array[i].next!=-1){
		cnt++;
		i = array[i].next;
	}
	return cnt;
}
//这个函数的什么作用呢?就是数清楚节点的个数,因为题目很坏
//他会输入一些无用的节点,程序用一次遍历去遍历出到底
//输入者输入了多少个结点。
void PrintList(int head,struct node array[])
{
	int idx = head;
	while(array[idx].next != -1){
		printf("%05d %d %05d\n",idx,array[idx].data,array[idx].next);
		idx = array[idx].next;
	}
	printf("%05d %d %d",idx,array[idx].data,array[idx].next);
}
//这就是根据索引也就是next进行遍历,输出满足格式打印
int ReverseList(struct node array[],int *head,int k){
	int cnt;
	if(k==1)
		return -1;
	cnt = count(*head,array);
	int i,ptr1,ptr2,ptr3,firstflag=0,nexthead=*head,lastend=-2;
	while(cnt>=k){
		ptr1 = nexthead;
		ptr2 = array[ptr1].next;
		for(i=1;i<k;i++)
		{
			ptr3 = array[ptr2].next;//临时变量粗存老的下一条地址
			array[ptr2].next =ptr1;//将1的索引放进2的里面
			ptr1= ptr2;//结点转向下一个地址
			ptr2 = ptr3;//老结点继续唯一
		}
		array[nexthead].next=ptr3;
		if(firstflag==0){
			lastend = nexthead;
			*head = ptr1;
		}else{
			array[lastend].next = ptr1;
			lastend = nexthead;
		}
		firstflag++;
		nexthead = ptr2;
		cnt-=k;
	}
	
}
int main()
{
	head = Input(workArray);
	ReverseList(workArray,&head,k);
	PrintList(head,workArray);
	return 0;
}

拿到程序直接先看主函数,其他先不要看。
它调用的是一个输入,再者是处理,最后是输出。

int Input(struct node array[]){
	int i,inputHead,inputLength;
	int index,data,next;
	scanf("%d %d %d",&inputHead,&inputLength,&k);
	for(i=0;i<inputLength;i++){
		scanf("%d %d %d",&index,&data,&next);
		array[index].data = data;
		array[index].next = next;
	}
	return inputHead;
}

解释:将一个结构体数组作为一个函数参数传进来,那么结构体数组长什么样子呢?

struct node{
	int data;
	int next;
}workArray[MAXLEN];
int k,head;//k是你需要反转的个数
struct node workArray[MAXLEN];//结构体数组

结构体就存放数据域和下一个索引地址的域,在对格式的输入时,先输入头结点,然后是输入你想要存入的个数,最后输入想要逆转结点个数。
将输入的一个参数作为数组的索引进行存储,这是亮点!
当输入完毕时,会发现进入了,下一个模块,反转链表!

int ReverseList(struct node array[],int *head,int k){
	int cnt;
	if(k==1)
		return -1;
	cnt = count(*head,array);
	int i,ptr1,ptr2,ptr3,firstflag=0,nexthead=*head,lastend=-2;
	while(cnt>=k){
		ptr1 = nexthead;
		ptr2 = array[ptr1].next;
		for(i=1;i<k;i++)
		{
			ptr3 = array[ptr2].next;//临时变量粗存老的下一条地址
			array[ptr2].next =ptr1;//将1的索引放进2的里面
			ptr1= ptr2;//结点转向下一个地址
			ptr2 = ptr3;//老结点继续唯一
		}
		array[nexthead].next=ptr3;
		if(firstflag==0){
			lastend = nexthead;
			*head = ptr1;
		}else{
			array[lastend].next = ptr1;
			lastend = nexthead;
		}
		firstflag++;
		nexthead = ptr2;
		cnt-=k;
	}
	
}

代码需要一行行来看,当自身能力越来越强时,看的代码速度就会越来越快。因为给出反转链表的个数,却没有确定自身链表有几个,所以先遍历链表。

int count(int head,struct node array[]){
	int i,cnt = 1;
	i = head;
	while(array[i].next!=-1){
		cnt++;
		i = array[i].next;
	}
	return cnt;
}

这是用索引遍历,通过-1确定整个流程安排。然后继续阅读代码,会发现申明了一大堆变量,ptr1,ptr2,ptr3都是拿来用反转链表的后两个,是拿来存索引的,索引存进去的,我就可以实现整个链表的存储。根据结点个数和反转的个数进行反转链表,类似于链表的插入,这里看我的代码注释就很清楚了。当就一个元素反转,他需要存储的是自己为最后一个地址。可以参考这张图
在这里插入图片描述
当这些都逆转完毕,索引都存储好时,最后来一个遍历就结束战斗

void PrintList(int head,struct node array[])
{
	int idx = head;
	while(array[idx].next != -1){
		printf("%05d %d %05d\n",idx,array[idx].data,array[idx].next);
		idx = array[idx].next;
	}
	printf("%05d %d %d",idx,array[idx].data,array[idx].next);
}
发布了63 篇原创文章 · 获赞 2 · 访问量 1452

猜你喜欢

转载自blog.csdn.net/m0_37149062/article/details/105047854