OJ 单链表

PAT中有关链表的题一般都是用顺序结构来表示,即将链表的节点储存在一个很大的数组中,数组下标就是节点的地址,节点结构中有一个next成员,储存着逻辑上下个节点的下标,用-1来表示空值。

//基本的节点结构
struct Node
{
    //数据
    int data;
    //下个节点的坐标
    int next;
};

考察范围无非增查删改反转这些,有一个方法可以在不破坏原有的逻辑顺序的前提下使用stl算法

为节点结构添加 address order 成员

struct Node
{
    int data;
    int next;
    //添加成员
    int address;  //记录节点的地址
    int order; //记录节点在链表中的逻辑顺序
    Node():
    order(INT32_MAX) //order默认为最大值
    { }
};

用一个vector来保存节点
节点的地址范围为 00000-99999

vector<Node> linklist(100000);    //足够容纳所有的地址

先按照链表中节点的顺序遍历,为每个节点赋值其order

int order = 0;
for (auto it = head; it != -1; it = linklist[it].next)
{
    linklist[it].order = order++;
}

再根据order大小排序,将节点聚集
根据order排序后,节点聚集在一起,下标失去地址的意义,但节点的相对次序还是和链表中一样

//order小的排在前面,即链表中的逻辑顺序
sort(linklist.begin(), linklist.end(), [](const Node& lhs, const Node&rhs) {
        return lhs.order < rhs.order;
    });

此时可以直接用stl的方法插入、删除节点
一个翻转链表的例子

vector<Node> linklist(100000);
    int head;
    int N;

    cin >> head >> N;

    while (N--)
    {
        int address, data, next;
        cin >> address >> data >> next;
        linklist[address] = Node(address, data, next);
    }

    int order = 0;
    for (auto it = head; it != -1; it = linklist[it].next)
    {
        linklist[it].order = order++;
    }

    sort(linklist.begin(), linklist.end(), [](const Node& lhs, const Node&rhs) {
        return lhs.order < rhs.order;
    });
    //将后面多余的空节点删掉
    linklist.resize(order);
    //可以直接使用翻转函数
    reverse(linklist.begin(), linklist.end());

    for (auto it = linklist.begin(); it != linklist.end(); ++it)
    {
        if (it != linklist.end() - 1)
        {
        //注意要用(it + 1)->address输出下一个节点的地址
        //因为next没有在reverse后更新,也可以更新next后再将next输出
            printf("%05d %d %05d\n", it->address, it->data, (it + 1)->address);
        }
        else
        {
            printf("%05d %d -1\n", it->address, it->data);
        }
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值