美文网首页
1025 反转链表

1025 反转链表

作者: 初见还是重逢 | 来源:发表于2019-03-08 20:28 被阅读0次

给定一个常数 K 以及一个单链表 L,请编写程序将 L 中每 K 个结点反转。例如:给定 L 为 1→2→3→4→5→6,K 为 3,则输出应该为 3→2→1→6→5→4;如果 K 为 4,则输出应该为 4→3→2→1→5→6,即最后不到 K 个元素不反转。

输入格式:

每个输入包含 1 个测试用例。每个测试用例第 1 行给出第 1 个结点的地址、结点总个数正整数 N (≤10^​5)、以及正整数 K (≤N),即要求反转的子链结点的个数。结点的地址是 5 位非负整数,NULL 地址用 −1 表示。

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

Address Data Next
其中 Address 是结点地址,Data 是该结点保存的整数数据,Next 是下一结点的地址。

输出格式:

对每个测试用例,顺序输出反转后的链表,其上每个结点占一行,格式与输入相同。

输入样例:

00100 6 4
00000 4 99999
00100 1 12309
68237 6 -1
33218 3 00000
99999 5 68237
12309 2 33218

输出样例:

00000 4 33218
33218 3 12309
12309 2 00100
00100 1 99999
99999 5 68237
68237 6 -1

思路:

本题难度略高,有两个测试用例不好通过,一是大量的节点数据,查找超时的问题,二是不一定所有的节点都是有效节点,对于这种情况需要删除无效的节点
例如这种:

00100 6 2
00000 4 99999
00100 1 12309
68237 6 -1
33218 3 00000
99999 5 77777
12309 2 33218

在这个测试用例中,节点5的下个地址是77777,但是并没有节点的地址是77777,因此在链表中5之后的节点就应该要删除,最后的结果应该是2-1-4-3-5


image

另外本题还需要注意的是:对于最后小于K的节点,是不需要逆序的。例如这个测试用例,最后剩两个节点5,6,个数是小于4的,因此5,6就不需要逆序,最后的结果应该是4-3-2-1-5-6

00100 6 4
00000 4 99999
00100 1 12309
68237 6 -1
33218 3 00000
99999 5 68237
12309 2 33218

image

而解决查找速度的问题,本人使用了< algorithm >库中的find_if函数
关于find_if函数,以后如有机会可以详细介绍一下,在这里的关键代码如下:

先定义判断函数:

class judge//对find_if算法的第三个函数参数的定义
{
private:
    int address;//judge函数是对节点node a进行判断,判断其地址是不是int address
public:
    judge(int add) :address(add){}//必须对该类进行构造函数的定义,由于在find_if中,第三个参数需要传入一个变量add,需要判断该变量与node中的地址是否相同
    bool operator()(node a)//由于find_if第三个参数无法传入自己的node值,因此需要对操作符()进行重新定义,使其可以使用操作符来间接调用自己的值
    {
        return a.address == address;//判断judge(add),如果a与node a的address相同返回true
    }
};

可以直接调用函数查找下一个节点:

vector<node>::iterator it;//先定义指针
it = find_if(L.begin(), L.end(), judge(first));
//找到地址为first的节点

以上是该题的两个难点的解决方法。

最后总结一下整个程序的思路


image

代码:

反转链表

//1025  反转链表
//本题有两个难点,一是对于大量的节点数据,查找超时的问题,二是不一定所有的节点都是有效的节点,无效的节点应该删除
#include<iostream>
#include<vector>
#include<algorithm>

using namespace std;

struct node//首先需要定义节点结构体
{
    int address;
    int data;
    int next;
};

void exchange(node &a, node &b)//定义交换两个节点的函数
{
    node temp;
    temp = a;
    a = b;
    b = temp;
    return;
}

class judge//对find_if算法的第三个函数参数的定义
{
private:
    int address;//judge函数是对节点node a进行判断,判断其地址是不是int address
public:
    judge(int add) :address(add){}//必须对该类进行构造函数的定义,由于在find_if中,第三个参数需要传入一个变量add,需要判断该变量与node中的地址是否相同
    bool operator()(node a)//由于find_if第三个参数无法传入自己的node值,因此需要对操作符()进行重新定义,使其可以使用操作符来间接调用自己的值
    {
        return a.address == address;//判断judge(add),如果a与node a的address相同返回true
    }
};

int main()
{
    int first, N, K;
    cin >> first >> N >> K;
    //存入第一行的首地址,节点个数,已经每隔K反转的值

    vector<node> L;//定义node数组L
    node temp;//临时存放node的值
    int  data, address, next;//存放每一行的地址,数据,下一个地址
    //将所有数据读取,然后每一行一次存入L中
    for (int i = 0; i < N; i++)
    {
        scanf("%d %d %d", &address, &data, &next);
        temp.address = address;
        temp.data = data;
        temp.next = next;
        L.push_back(temp);
    }
    //至此,将所有数组存储完毕

    vector<node>::iterator it;//定义数组指针
    it = find_if(L.begin(), L.end(), judge(first));//找到地址为first的节点使用find_if()函数,注意第三个变量是一个函数,函数的定义在上面,这个函数可以传入参数first
    exchange(*it, L[0]);//将地址为首地址的节点与L数组的第一个交换

  //从第二个元素开始查找,找到最后一个元素,将所有的节点按照节点的顺序进行排序
    for (int i = 1; i < N; i++)
    {
        it = find_if(L.begin() + i, L.end(), judge(L[i - 1].next));//从i的元素开始查找,查找地址为L[i-1]的下一个地址
        if (it != L.end())//如果找到将其与L[i]的后一个节点进行交换
            exchange(*it, L[i]);
        else//如果没有找到,证明i-1节点后面断了,后面的元素需要都删除
        {
            L.erase(L.begin() + i, L.end());
            break;
        }
    }

    //将有效的节点进行题目要求转序
    int count = L.size() / K;//计算需要转序的次数,例如有6个节点,K=4,只需要转序一次,K=2则需要转序3次
    it = L.begin();
    for (int i = 0; i < count; i++)//转序count次,每一次将it与it+K之间的进行转序
    {
        reverse(it, it + K);
        it += K;
    }

    //转序完后将每一个节点的next地址改为下一个节点的地址,并将最后一个节点的next地址设为-1
    for (int i = 0; i < L.size() - 1; i++)
    {
        L[i].next = L[i + 1].address;
    }
    L[L.size() - 1].next = -1;

    //按照要求输出结果
    for (int i = 0; i < L.size() - 1; i++)
    {
        printf("%05d %d %05d\n", L[i].address, L[i].data, L[i].next);
    }
    printf("%05d %d %d\n", (L.end() - 1)->address, (L.end() - 1)->data, (L.end() - 1)->next);

    return 0;
}

相关文章

网友评论

      本文标题:1025 反转链表

      本文链接:https://www.haomeiwen.com/subject/xqmdpqtx.html