您的位置:首页 > 理论基础 > 数据结构算法

数据结构 PAT 02-线性结构2 Reversing Linked List 单链表实现

2015-09-30 19:20 776 查看
02-线性结构2 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.


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 (≤10​5​​)
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


自己用了一种好蠢的方法,再加上又是C语言,真的好蠢;其实可以用静态链表,明天更新

#include <stdio.h>
#include <stdlib.h>
struct Node
{
int address;
unsigned data; // 整数<=105
int nextAddress; // 下个结点的五位数地址
struct Node *next; // 连接下个结点的指针
};
typedef struct Node LNode;
typedef LNode *List;

List listCreate()
{
List l, rear, tempPtr; // 创建链表指针
int firstNodeAddress, N, K;
int i, address, data, nextAddress;

scanf("%d %d %d", &firstNodeAddress, &N, &K);
/* 创建一个头结点,存放链表信息 */
l = (List)malloc(sizeof(LNode));
l->address = N; // 输入结点的总个数
l->data = K; // 反向子列的长度
l->nextAddress = firstNodeAddress; // 第一个结点的数字地址
l->next = NULL;
rear = l;

/* 依输入顺序用尾插法,插入各结点 */
for (i = 0; i < N; i ++)
{
scanf("%d %d %d", &address, &data, &nextAddress);
tempPtr = (List)malloc(sizeof(LNode));
tempPtr->address = address;
tempPtr->data = data;
tempPtr->nextAddress = nextAddress;
tempPtr->next = NULL;
rear->next = tempPtr;
rear = tempPtr;
}
return l;
}

List listSort(List L)
{
if (L==NULL) return NULL;

List tempPtr, rear, prePtr, newPtr, lNode;
int N, realN, nextPosition;
realN=0;
N = L->address; // 输入结点的总数N
newPtr = (List)malloc(sizeof(LNode)); // 新头结点指向链表
newPtr->next = L->next;

L->next = NULL; // 将原头结点与原链表断开,用来准备指向排好序的链表
rear = L;
nextPosition = rear->nextAddress; // 存放下一个结点的数字地址
while (nextPosition != -1)
{
prePtr = newPtr; // tempPtr的前驱指针
tempPtr = prePtr->next;

while (tempPtr && tempPtr->address!=nextPosition)
{
prePtr = tempPtr; // pre指向其前驱
tempPtr = tempPtr->next;
}
if (tempPtr->address == nextPosition)
{
/* 将当前结点接入新链 */
lNode = tempPtr;
rear->next = lNode;
rear = lNode;

realN++; // 计算排序后链表的真实长度
prePtr->next = tempPtr->next; // 从旧链中删除该结点
rear->next = NULL; // 新链尾指针的next置空
}
// 给新链表下一个结点数字地址赋值
nextPosition = rear->nextAddress;
}
while (newPtr) // 删除多余结点
{
tempPtr =newPtr;
newPtr=newPtr->next;
free(tempPtr);
}
L->address = realN; // 链表中有效结点的总个数
return L;
}

// 思路:创建一新临时头结点,指向链表,再将原头结点的next置空,并对需要反转的进行头插入法即可(有头结点方便操作)
List listReverse(List L)
{
int N, K, M, i, j;
List header, lNode, tempHeader, tempPtr;
N = L->address; // 链表中的总结点
K = L->data; // 反转的个数
M = N/K; // 需要反转的轮数

// 新头结点指向原链
tempHeader = (List)malloc(sizeof(LNode));
tempHeader->next = L->next;
tempPtr = tempHeader->next;

L->next = NULL;
header = L;
j = 0;
for (i = 0; i < M*K; i++)
{
lNode = tempPtr;
// 从原链表中去除结点
tempHeader->next = tempPtr->next;
tempPtr = tempPtr->next;
// 头插入法插入结点
lNode->next = header->next;
header->next = lNode;
j++;
if (j == K)
{
// 下一轮开始头插,必须将指针移动到链表尾部
while (header->next)
header = header->next;
j = 0;
}
}
if (M != 0)
header->next = tempHeader->next;
free(tempHeader); // 释放临时结点
// 将地址信息进行处理
L->nextAddress = L->next->address;
tempPtr = L->next;
while (tempPtr)
{
if (tempPtr->next)
tempPtr->nextAddress = tempPtr->next->address;
else
tempPtr->nextAddress = -1;
tempPtr = tempPtr->next;
}
return L;
}

void printList(List L)
{
int i, N;
List tempNode = L->next; //pointer of firstNode
N = L->address; // 结点总数
for(i = 0; i< N; i++)
{
printf("%05d ", tempNode->address);
printf("%d ", tempNode->data);
if(tempNode->nextAddress == -1)
printf("%d", tempNode->nextAddress);
else
printf("%05d", tempNode->nextAddress);
printf("\n");
tempNode = tempNode->next;
}
}

int main()
{
/* 创建并读入链表 */
List l = listCreate();
/* 将链表排序 */
l = listSort(l);
/* 反转链表 */
l = listReverse(l);
/* 打印链表 */
printList(l);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: