PATB1075 链表元素分类

题目描述

给定一个单链表,请编写程序将链表元素进行分类排列,使得所有负值元素都排在非负值元素的前面,而 [0, K] 区间内的元素都排在大于 K 的元素前面。但每一类内部元素的顺序是不能改变的。例如:给定链表为 18→7→-4→0→5→-6→10→11→-2,K 为 10,则输出应该为 -4→-6→-2→7→0→5→10→18→11。

输入格式:

每个输入包含一个测试用例。每个测试用例第 1 行给出:第 1 个结点的地址;结点总个数,即正整数N (≤105);以及正整数K (≤103)。结点的地址是 5 位非负整数,NULL 地址用 −1 表示。

接下来有 N 行,每行格式为:

Address Data Next

其中 Address 是结点地址;Data 是该结点保存的数据,为 [−105,105] 区间内的整数;Next 是下一结点的地址。题目保证给出的链表不为空。

输出格式:

对每个测试用例,按链表从头到尾的顺序输出重排后的结果链表,其上每个结点占一行,格式与输入相同。

输入样例:

00100 9 10
23333 10 27777
00000 0 99999
00100 18 12309
68237 -6 23333
33218 -4 00000
48652 -2 -1
99999 5 68237
27777 11 48652
12309 7 33218

输出样例:

33218 -4 68237
68237 -6 48652
48652 -2 12309
12309 7 00000
00000 0 99999
99999 5 23333
23333 10 00100
00100 18 27777
27777 11 -1

问题分析

处理流程:

输入结点地址、数据、下一个结点地址;重排;按格式输出。

处理细节:
  • 数据存储:用结构体数组存储,本题目中是 node 类型的 数组 list。list 下标是本结点地址,结点 node 中保存数据 data 和 下一个结点的地址;结点地址保存在 vector 类型的数组中,按分类要求分为三个部分 v[0]、v[1]、v[2];
  • 输入输出:输入就按照 地址、数据、下一结点地址输入即可;输出的格式柳神写的是非常巧妙的,第一次输出时仅输出头结点的地址和数据,把下一个结点的地址交给下一个循环输出。之后的每个结点输出两次它的结点值,第一次是在上一行的最后输出,是相对于上一次输出的下一个地址,然后换行,输出本次结点值。这样就把问题做了简化。抓住了上一个结点的下一个结点与本结点相同这一问题特性;
  • 分类处理:这是本题的核心,按照链表顺序分类处理,我想这是一句很好的总结了。首先怎么按照链表顺序读我们的输入呢?其实陈姥姥已经铺好了路:输入中是有第一个结点的地址的,而且已经用结构体存储好了它的结点地址,那么再加上循环,就可以正常的按顺序读取了;接下来就是在每次循环中处理,如果结点值是小于 0 的,那么放入 vec[0];结点值在[0, k] 区间的,放入vec[1];剩下的放入vec[2]。说白了就是对链表按区间分类,但每类中的前后顺序都与输入时一致

代码

#include <iostream>
#include <vector>
struct node{
    int data, next;
}list[100000];
std::vector<int> vec[3];
int main(){
    int sadr, n, k, tmpadr;
    std::cin >> sadr >> n >> k;
    for (int i = 0; i < n; i++) { // 循环输入
         std::cin >> tmpadr;
         std::cin >> list[tmpadr].data >> list[tmpadr].next; 
    }
    int p = sadr;
    while(p != -1) {
        int data = list[p].data;
        if (data < 0) vec[0].push_back(p);
        else if (data >= 0 && data <= k) vec[1].push_back(p);
        else vec[2].push_back(p);
        p = list[p].next;
    }
    int flag = 0; // 标记是否有过输出
    for (int i = 0; i < 3; i++) {
         for (int j = 0; j < vec[i].size(); j++) {
              if (flag == 0) {printf("%05d %d ", vec[i][j], list[vec[i][j]].data); flag = 1;}
              else printf("%05d\n%05d %d ", vec[i][j], vec[i][j], list[vec[i][j]].data);
         }
    }
    printf("-1");
    return 0;
}

小结

好好读题,题目中总有线索;

这种存储比较多的情况可以考虑使用结构体;

解法参考

题目解法来自柳神,本人只是照敲、学习。

https://www.liuchuo.net/archives/4094

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值