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

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 (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.

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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值