题意:给出N个结点的地址address、数据域data以及指针域next,然后给出链表的首地址,要求去除链表上权值的绝对值相同的结点(只保留第一个),之后把未删除的结点按链表连接顺序输出,接着把被删除的结点也按在原链表中的顺序输出。
样例:原链表为21→-15→-15→-7→15,去除权值的绝对值相同的结点后的链表为21→-15→7,被删除的部分为-15→15。
思路:
- 使用静态链表存储节点,并设置一个数组来记录节点的绝对值。
- 遍历链表,借助标记数组来获取未删除的节点数和要删除的节点数。
- 依据题意对结果进行输出。
代码如下:
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn = 100000;
struct Node
{
//节点地址、值、下一个节点的地址、节点顺序
int address, key, next, order;
Node(int a=0,int k=0,int n=0,int o=2*maxn):address(a),key(k),next(n),order(o){}
};
bool cmp(Node A,Node B)
{
return A.order < B.order;
}
//存储节点的静态链表、标记数组
Node datas[maxn];
bool recode[maxn] = { false };
int main()
{
int first, num,keep_count = 0, invaild_count = 0;
scanf("%d %d", &first, &num);
//读入数据
for (int i = 0;i < num;i++)
{
int a;
scanf("%d", &a);
scanf("%d %d", &datas[a].key, &datas[a].next);
datas[a].address = a;
}
//遍历链表
while (first != -1)
{
//由标记数组进行标记
if (!recode[abs(datas[first].key)])
{
datas[first].order = keep_count++;
recode[abs(datas[first].key)] = true;
}
else
{
//将要删除节点的顺序想后移,比保留的节点大,比无效节点小
datas[first].order = maxn + invaild_count++;
}
first = datas[first].next;
}
sort(datas, datas + maxn, cmp);
//按要求进行输出
int count = keep_count + invaild_count;
for (int i = 0;i < count;i++)
{
if (i == keep_count -1 || i==count-1)printf("%05d %d -1\n", datas[i].address, datas[i].key);
else printf("%05d %d %05d\n", datas[i].address, datas[i].key, datas[i+1].address);
}
return 0;
}