浙大数据结构第二周之02-线性结构3 Reversing Linked List

这篇具有很好参考价值的文章主要介绍了浙大数据结构第二周之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.

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

简单翻译:

本题就是输入了一个乱序的链表,只是告诉你每个节点的地址,数据域与下一个节点的地址,要先顺出一个完整链表,然后还要倒置指定长度,如果剩下长度不足指定长度就不倒置

主要思路:

首先要有一个结构体数组用来存储原始数据的数据域和下一个节点地址,当前节点的地址用另一个数据结构存储,可以是链表也可以是数组

如果用链表,则第一个存储原始数据的结构体数组的下标就是原始数据的节点地址,通过遍历下标(利用了结构体里存储的下一个节点地址)实现创建链表

为了实现倒置链表,这个创建的链表是双向链表,这样倒置时利用双指针,外层循环条件是现在移动位置加上移动距离小于链表长度,先将后指针移动到子序列末尾,然后将前后指针所指的数据域(里面是当前节点“地址”(不是真节点地址))交换,然后前指针后移,后指针前移,两者相交(相等或前跑到后的后面,这里可以用最近学的离散命题知识解释,记p:相等, q:到后面,¬(p∨q) 等价于¬p ∧¬q)时结束内层循环

完成倒置后打印输出,遍历链表,从中取出节点”地址“,用这个”地址“访问结构体数组取出里面存放的数据域,打印下一个节点”地址“则是取链表下一位,要判断链表下一位是不是空,如果是空就打印-1且不带换行

如果用数组,思路基本一致

第一次写错误:

题干将N是节点数量,不是链表长度,可能有不在链表上节点

代码实现:

两个数组版:

#include <stdio.h>
#include <stdlib.h>
#define maxsize 100002
 
struct LNode {
    int Data;
    int Next;
} a[maxsize];	//a这个数组是用来存储数据 
 
int list[maxsize];  //每个结点的地址
int Head, N, K, p;  //第一个节点地址,所有结点数,翻转子序列长度
 
int main() {
    scanf("%d%d%d", &Head, &N, &K);
 
    list[0] = Head;
    for (int i = 0; i < N; ++i) {
        int index, data, next;
        scanf("%d%d%d", &index, &data, &next);
        a[index].Data = data;
        a[index].Next = next;
    }
 
    p = a[Head].Next;
    int sum = 1;
    while (p != -1) {
        list[sum++] = p;
        p = a[p].Next;
    }
 
    int j = 0;
    while (j + K <= sum) {	//双指针法 
        int left = j, right = j + K - 1;
        while (left < right) {
            int temp = list[left];	//操作的是记录地址的指针 
            list[left] = list[right];
            list[right] = temp;
            left++;
            right--;
        }
        j = j + K;
    }
 
    for (int i = 0; i < sum - 1; ++i) {
        int id = list[i];  //第i个结点的索引
        printf("%05d %d %05d\n", id, a[id].Data, list[i + 1]);	//直接打印交换后的下一个地址,原来记录在a里的下一位没用了 
    }
    printf("%05d %d -1\n", list[sum - 1], a[list[sum - 1]].Data);
    return 0;
}
/*这种思路桥面在用两个大数组,一个用来记录当前节点的数据域与下一个指针,另一个数组用来记录当前节点的地址
双指针法交换节点的时候其实交换当前节点的地址即可*/ 

链表+数组版文章来源地址https://www.toymoban.com/news/detail-558383.html

/*整体思路
用一个大数组用于保存原始数据,下标用于保存当前数据地址
创建一个链表,只保存当前节点地址,用于倒置,倒置后只用
通过链表保存的当前节点地址到结构体数组中访问对应的数据与下一个节点地址即可
*/
#include <stdio.h>
#include <stdlib.h>
#define MAX_SIZE 100005
#define END -1

/*存放当前节点地址链表的数据结构,双向链表*/
typedef struct Node ListNode;
typedef ListNode* List;
struct Node {
    List Previous;
    int Ip;
    List Next;
};

/*存放临时数据的结构体数组,下标表示当前地址*/
typedef struct Data Data;
struct Data {
    int Data, NextIp;
};
Data Info[MAX_SIZE];    //这个是一个结构体数组用来存储一开始给的无序数据

/*读取*/
void Read(int nodeNum) {    //这里命名为nodeNum是因为太坑了,还可能有节点不在链表上,题干说N只是节点数量
    for(int i = 0; i < nodeNum; i++) {
        int ip;
        scanf("%d", &ip);
        scanf("%d %d", &Info[ip].Data, &Info[ip].NextIp);
    }
    return;
}
/*尾插法*/
void Attach(int ip, List* rear) {
    /*申请一个新的节点*/
    (*rear)->Next = (List)malloc(sizeof(ListNode));
    List previous = *rear;
    (*rear) = (*rear)->Next;
    
    /*填充这个新的节点*/
    (*rear)->Previous = previous;
    (*rear)->Ip = ip;
    (*rear)->Next = NULL;
    return;
}
/*顺出一个正常链表*/
List CreateList(int headAddress, int* listLength) {
    int ptrInt = headAddress;
    List dummyHead = (List)malloc(sizeof(ListNode));
    List ptrList = dummyHead;
    ptrList->Next = NULL;
    while(ptrInt != END) {
        int data = Info[ptrInt].Data;
        int nextIp = Info[ptrInt].NextIp;
        Attach(ptrInt, &ptrList);
        ptrInt = Info[ptrInt].NextIp;
        (*listLength)++;
    }
    return dummyHead;
}
/*打印链表*/
void PrintList(List L) {
    List ptr = L->Next;
    while(ptr) {
        printf("%05d %d %05d", ptr->Ip, Info[ptr->Ip].Data, Info[ptr->Ip].NextIp);
        if(ptr->Next) printf("\n");
        ptr = ptr->Next;
    }
    return;
}
/*删除链表*/
void DeleteList(List L) {
    List ptr = L->Next;
    while(ptr) {
        List tmp = ptr;
        ptr = ptr->Next;
        free(tmp);
    }
    return;
}
void Swap(List* node1, List* node2) {
    int tmp = (*node1)->Ip;
    (*node1)->Ip = (*node2)->Ip;
    (*node2)->Ip = tmp;
    return;
}
void ReverseList(List L, int listLength, int reverseLength) {
    List ptrFront = L, ptrBack = L->Next;
    int ptrInt = 0;
    while(ptrInt + reverseLength <= listLength && ptrFront && ptrBack) {    //循环终止条件,最后剩余片段不够倒置长度
        for(int i = 0; i < reverseLength - 1; i++) {
            ptrBack = ptrBack->Next;
        }
        List nextStart = ptrBack;
        ptrFront = ptrFront->Next;
        while(ptrFront->Previous != ptrBack && ptrFront != ptrBack  ) {
            Swap(&ptrFront, &ptrBack);
            ptrFront = ptrFront->Next;
            ptrBack = ptrBack->Previous;
        }
        ptrFront = nextStart;
        ptrBack = nextStart->Next;
        ptrInt += reverseLength;
    }
    List ret = L->Next;
    while(ret) {
        int ip = ret->Ip; 
        printf("%05d %d ", ip, Info[ip].Data, Info[ip].NextIp);
        if(ret->Next != NULL) {
            printf("%05d\n", ret->Next->Ip);
        } 
        else printf("-1");
        ret = ret->Next;
    }
    return;
}
int main() {
    int headAddress, N, K;
    scanf("%d %d %d", &headAddress, &N, &K);

    Read(N);    //读入原始数据
    int listLength = 0;
    List initialList = CreateList(headAddress, &listLength);     //整理原始链表
    ReverseList(initialList, listLength, K); //操作链表:倒置
    DeleteList(initialList);    //删除链表
    return 0;
}

到了这里,关于浙大数据结构第二周之02-线性结构3 Reversing Linked List的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • ARTS打卡第二周之链表环的检测、gdb中disassemble的使用、底层学习建议、学习分享

    题目:链表中环的检测 自己的分析见博客《检测链表中是否存在环》 disassemble command是我读的一篇英语文章,这篇文章主要是介绍gdb反汇编命令的使用和参数。自己为了能够演示这篇文章里边的内容,特意自己使用汇编语言编写代码,然后写了一篇博客。 我这里使用下边的汇

    2024年02月11日
    浏览(27)
  • 自学嵌入式第二周之如何生成烧录到单片机内所必须的(.hex)文件

    Keil软件是一款辅助单片机编写程序,编译及运行程序,并产生单片机下载所必须的(.hex)文件,用于写入单片机内部的程序。 01 在桌面新建文件夹,以自己名字命名。 打开下载好的Keil软件,如图 02 选择菜单栏( 工程——新建工程),然后出现的对话框,保存在选- 桌面

    2024年04月26日
    浏览(28)
  • 数据结构与算法【02】—线性表

    CSDN系列专栏:数据结构与算法专栏 针对以前写的数据结构与算法系列重写(针对文字描述、图片、错误修复),改动会比较大,一直到更新完为止 通过前面数据结构与算法基础知识我们知道了数据结构的一些概念和重要性,那么本章总结下线性表相关的内容。当然,我用自己

    2024年02月05日
    浏览(34)
  • 【数据结构】第二章课后练习题——线性结构

    1、线性表是 一个有限序列,可以为空 2、链表中最常用的操作是在最后一个元素之后插入一个元素和删除最后一个元素,则采用 单循环链表 存储方式最节省运算时间 3、若某线性表中最常用的操作实在最后一个元素之后插入一个元素和删除第一个元素,则采用 仅有尾结点的

    2024年02月07日
    浏览(48)
  • 【数据结构】第二章——线性表(4)

    大家好,很高兴又和大家见面啦!!! 在前面的内容中我们介绍了线性表的第一种存储方式——顺序存储,相信大家经过前面的学习应该已经掌握了对顺序表的一些基本操作了。今天,我们将开始介绍线性表的第二种存储方式——链式存储。 线性表中的数据元素在存储时,

    2024年02月04日
    浏览(30)
  • 【数据结构】第二章——线性表(2)

    大家好,很高兴又和各位见面啦!!!在上一个篇章中,我们简单了解了一下线性表的基础知识以及一下重要的术语。在今天的篇章中我们将来开始正式介绍线性表的顺序存储——又称顺序表。我们将会在本章介绍什么是顺序表,对于顺序表的操作我们又应该如何实现。接下

    2024年02月03日
    浏览(29)
  • 【数据结构】第二章——线性表(3)

    大家好,很高兴又和大家见面了!!! 在上一篇中,咱们介绍了顺序表的基本概念,以及通过C语言实现顺序表的创建和对表长的修改。今天咱们将详细介绍一下使用C语言实现顺序表的增删改查。接下来,跟我一起来看看今天的内容吧!!! 我们先来回顾一下上一篇的内容,

    2024年02月04日
    浏览(36)
  • 【数据结构】第二章——线性表(1)

    大家好,很高兴又和大家见面啦!!!从今天开始,我们将进入线性表的学习。 线性表是算法题命题的重点。这类算法题实现起来比较容易且代码量较少,但是要求具有最优的性能(时间复杂度、空间复杂度),因此,我们应该牢固掌握线性表的各种基本操作(基于两种存储

    2024年02月03日
    浏览(33)
  • 扎实打牢数据结构算法根基,从此不怕算法面试系列之004 week01 02-04 使用泛型实现线性查找法

    在数组中逐个查找元素,即遍历。 在 扎实打牢数据结构算法根基,从此不怕算法面试系列之003 week01 02-03 代码实现线性查找法中,我们实现了如下代码: 之前实现的局限: 只支持int型。 需求: 支持所有的Java基本数据类型以及自定义的类类型。 很简单,很多语言都有这个处

    2023年04月16日
    浏览(31)
  • 浙大数据结构之09-排序1 排序

    给定N个(长整型范围内的)整数,要求输出从小到大排序后的结果。 本题旨在测试各种不同的排序算法在各种数据情况下的表现。各组测试数据特点如下: 数据1:只有1个元素; 数据2:11个不相同的整数,测试基本正确性; 数据3:103个随机整数; 数据4:104个随机整数;

    2024年02月11日
    浏览(22)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包