数据结构线性结构 —— 编程作业 03 :Reversing Linked List

Posted 大彤小忆

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据结构线性结构 —— 编程作业 03 :Reversing Linked List相关的知识,希望对你有一定的参考价值。

  题目描述: 给定一个常数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。

  输入格式: 每个输入文件包含一个测试用例。
        对于每种情况,第一行包含第一个结点的地址,结点的总数为 N N N( ⩽ 1 0 5 \\leqslant10^{5} 105),要反转的子列表的长度为K( ⩽ N \\leqslant N N)。结点的地址为5位非负整数,NULL用-1表示。
        接着是 N N 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

  代码实现:

#include <iostream>
#include<iomanip>
using namespace std;
#define MAXSIZE 100005

typedef int ElementType;
typedef struct node {
	ElementType data;
	ElementType next;
} Node;

//反转链表函数,每K个结点,反转一下 
int reverList(Node list[], int K, int head, int N)
{
	int flag = 1;
	int last_head;	//用于记录上一次反转后,子链表的最后结点地址
					//待与下一次反转的子链表的头部相连 
	int rev_head = head;//下一次待反转子链表的头结点地址 
	int mid_head = head;//反转过程中的中间结点地址 
	int mid_next;		//反转过程中的中间结点地址 

	while (N - K >= 0)//当剩余结点不够K个时,则不再反转 
	{
		N -= K;

		//反转子链表 
		for (int i = 0; i < K - 1; i++) 
		{
			mid_next = list[rev_head].next;
			list[rev_head].next = list[mid_next].next;
			list[mid_next].next = mid_head;
			mid_head = mid_next;
		}//反转子链表 

		//从第二次开始,需要把这次反转后的子链表的头结点连接到上一段的尾部 
		if (flag == 0) 
		{
			list[last_head].next = mid_head;
		}

		//记录第一次反转后的头结点,作为最终List的头结点并返回 
		if (flag) 
		{
			head = mid_head;
			flag = 0;
		}

		last_head = rev_head;
		rev_head = list[rev_head].next;//下次开始的头结点地址 
		mid_head = rev_head;
	}
	return head;
}

void printList(Node list[], int head)
{
	int next = head;
	while (list[next].next != -1) 
	{
		cout << setw(5) << setfill('0') << next << " " << list[next].data << " " << setw(5) << setfill('0') << list[next].next << endl;
		next = list[next].next;
	}
	cout << setw(5) << setfill('0') << next << " " << list[next].data << " " << list[next].next << endl;
}

int main()
{
	int Head, N, K;  //Head为第一个结点的地址,N为结点的总数,K为要反转的子列表的长度
	cin >> Head >> N >> K;
	Node list[MAXSIZE];
	int i, Address, Data, Next;  //Address是结点的位置,Data是一个整数,Next是下一个结点的位置
	for (i = 0; i < N; i++) 
	{
		cin >> Address >> Data >> Next;
		list[Address].data = Data;
		list[Address].next = Next;
	}
	int next = Head;
	int num = 1;//所给数据结点并不都是链表中的结点,用于计数真正的结点个数 
	while (list[next].next != -1) {
		num++;
		next = list[next].next;
	}
	if (K > 1)	//如果是1,则不需要反转,原序输出 
		Head = reverList(list, K, Head, num);
	printList(list, Head);

	system("pause");
	return 0;
}

  测试: 输入样例的测试效果如下图所示。

在这里插入图片描述

以上是关于数据结构线性结构 —— 编程作业 03 :Reversing Linked List的主要内容,如果未能解决你的问题,请参考以下文章

数据结构线性结构 —— 编程作业 04 :Pop Sequence

数据结构线性结构 —— 编程作业 02 :一元多项式的乘法与加法运算

博客作业03--栈和队列

博客作业03--栈和队列

数据结构基本概念 —— 编程作业 03 :二分查找

03 数组:为什么很多编程语言中数组都从0开始编号?