题目
题目详解
就是一个静态链表删除元素的数据结构类型题目,这题最坑的地方在于输出的时候需要地址五位数补0,如果是-1则不用补,导致你明明是对的,还以为是错误的。。🤷♂️
- 我用队列存储删除的结点的地址,然后后面再进行连接即可。
解题代码
基本变量
int head, rm_head = -1; //分别用于存储两个链表的头结点地址 int N; struct node { int val; int next; node() : val(0), next(-1) {} } linklist[MaxN]; queue<int> St; //存储被删除结点的地址 bitset<MaxN> check(0); //用于查重
Input函数
//输入和构建链表 void Input() { scanf("%d%d", &head, &N); int c = N; while (c--) { int addr, val, next; scanf("%d%d%d", &addr, &val, &next); linklist[addr].val = val; linklist[addr].next = next; } }
handle函数
//处理链表的去重问题 void handle() { //正常删除链表结点的处理方式 int pre = head; check[abs(linklist[head].val)] = 1; for (int i = linklist[pre].next; i != -1; i = linklist[i].next) { int val = abs(linklist[i].val); if (!check[val]) { check[val] = 1; pre = i; }//一旦出现重复结点,把这个结点删除就行,删除结点的操作需要双指针辅助 else { linklist[pre].next = linklist[i].next; St.push(i); } } if (St.empty()) return; //根据队列进行正确连接 int num = St.front(); St.pop(); rm_head = num; while (!St.empty()) { linklist[num].next = St.front(); num = linklist[num].next; St.pop(); } linklist[num].next = -1; }
print函数
//打印链表即可---注意小坑--(地址打印五位数字,少了补0,-1时不能打印五位数) void print() { handle(); for (int i = head; i != -1; i = linklist[i].next) { if (linklist[i].next != -1) printf("%05d %d %05d\n", i, linklist[i].val, linklist[i].next); else { printf("%05d %d %d", i, linklist[i].val, linklist[i].next); } } if (rm_head == -1) return; printf("\n"); for (int i = rm_head; i != -1; i = linklist[i].next) { if (linklist[i].next != -1) printf("%05d %d %05d\n", i, linklist[i].val, linklist[i].next); else { printf("%05d %d %d", i, linklist[i].val, linklist[i].next); } } }
整合代码提交
效率还行
#include<bits/stdc++.h> #define MaxN 100000 using namespace std; int head, rm_head = -1; //分别用于存储两个链表的头结点地址 int N; struct node { int val; int next; node() : val(0), next(-1) {} } linklist[MaxN]; queue<int> St; //存储被删除结点的地址 bitset<MaxN> check(0); //用于查重 //输入和构建链表 void Input() { scanf("%d%d", &head, &N); int c = N; while (c--) { int addr, val, next; scanf("%d%d%d", &addr, &val, &next); linklist[addr].val = val; linklist[addr].next = next; } } //处理链表的去重问题 void handle() { //正常删除链表结点的处理方式 int pre = head; check[abs(linklist[head].val)] = 1; for (int i = linklist[pre].next; i != -1; i = linklist[i].next) { int val = abs(linklist[i].val); if (!check[val]) { check[val] = 1; pre = i; }//一旦出现重复结点,把这个结点删除就行,删除结点的操作需要双指针辅助 else { linklist[pre].next = linklist[i].next; St.push(i); } } if (St.empty()) return; //根据队列进行正确连接 int num = St.front(); St.pop(); rm_head = num; while (!St.empty()) { linklist[num].next = St.front(); num = linklist[num].next; St.pop(); } linklist[num].next = -1; } //打印链表即可---注意小坑--(地址打印五位数字,少了补0,-1时不能打印五位数) void print() { handle(); for (int i = head; i != -1; i = linklist[i].next) { if (linklist[i].next != -1) printf("%05d %d %05d\n", i, linklist[i].val, linklist[i].next); else { printf("%05d %d %d", i, linklist[i].val, linklist[i].next); } } if (rm_head == -1) return; printf("\n"); for (int i = rm_head; i != -1; i = linklist[i].next) { if (linklist[i].next != -1) printf("%05d %d %05d\n", i, linklist[i].val, linklist[i].next); else { printf("%05d %d %d", i, linklist[i].val, linklist[i].next); } } } int main() { Input(); print(); return 0; }