链表处理

PAT (Advanced Level) Practice 链表题

目录

  • 《算法笔记》 重点摘要:静态链表
  • 1032 Sharing (25)
  • 1052 Linked List Sorting (25)
  • 1097 Deduplication on a Linked List (25)
  • 1133 Splitting A Linked List (25)
  • 附: 动态链表

《算法笔记》 7.3 链表 重点摘要

静态链表 ⭐

(1) 定义

结构体类型名和结构体变量名尽量不同

struct Node{
int address; // 记录地址(若后面排序则不能以数组下标代替)
typename data;
int next;
XXX...
} node[100001];
(2) 初始化
  • 遍历所有结点,将性质变量标记为比正常情况(如在所给链表上)下更小的数字
for (int i = 0; i < 100001; i++){
node[i].XXX = 0;
}
  • 输入节点时直接将性质变量的初始值压入
int n, head, address, key, next;
scanf("%d%d", &n, &head);
for (int i = 0; i < n; i++){
scanf("%d%d%d", &address, &key, &next);
node[address] = {address, key, next, 0};
}
(3) 标记

依据题目所给链表首地址和各结点信息遍历链表上的结点,标记性质,记录个数

int p = head, count = 0;
while (p != -1){
XXX = 1;
count++;
p = node[p]->next;
}
int count = 0;
for (int p = head; p != -1; p = node[p].next){
node[p].XXX = 1;
count++;
}
(4) 排序
bool cmp (Node a, Node b){
if (a.XXX == -1 || b.XXX = -1){
// 比较标记性质,若有无效点此性质较小 -> 被放到数组后面
return a.XXX > b.XXX;
}
else{
// 按要求排序
}
}

1032 Sharing (25)

题目思路

  • 链表结点中添加性质变量 inFirst 记录是否在第一个链表中
  • 初始化时将 inFirst 均置为 false
  • 结点输入完毕后,遍历第一条链表,令结点 inFirst = true
  • 遍历第二条链表,检查结点 inFirst,若为 true,break跳出循环
  • 检查第二条链表循环变量
    • 若未到链表尾,说明找到了和第一条链表共享的结点,按 %05d 输出地址
    • 若为 -1 说明到链表尾未找到,输出 -1
#include<iostream>
using namespace std;
struct Node{
char data;
int next;
bool inFirst;
} node[100001];
int main()
{
int head1, head2, n, address, next, p;
char data;
scanf("%d%d%d", &head1, &head2, &n);
for (int i = 0; i < n; i++){
scanf("%d %c %d", &address, &data, &next);
node[address] = {data, next, false};
}
for (p = head1; p != -1; p = node[p].next)
node[p].inFirst = true;
for (p = head2; p != -1; p = node[p].next)
if (node[p].inFirst == true) break;
if (p == -1) printf("-1");
else printf("%05d", p);
return 0;
}

1052 Linked List Sorting (25)

题目思路

  • 结点中添加性质变量 inList,用 int 型的 0/1 来表示,便于排序中比较
  • 结点中要保留此结点的地址,因为按 key 排序后数组下标将不再能表示地址
  • 输入完成后,从头结点遍历链表,令 inList = 1 并 记录链表中的结点数
  • 排序函数将不在链表中的放到后面,在链表中的按 key 值排序,故排序后数组的前 count 个即为新链表
  • 输出时注意数组前一个结点的新 next 应当为数组下一个结点的地址,而非原链表的 next
#include<iostream>
#include<algorithm>
using namespace std;
struct Node{
int address, key, next, inList;
} node[100001];
bool cmp (Node a, Node b){ return !a.inList || !b.inList ? a.inList > b.inList : a.key < b.key; }
int main()
{
int n, head, address, key, next, count = 0;
scanf("%d%d", &n, &head);
for (int i = 0; i < n; i++){
scanf("%d%d%d", &address, &key, &next);
node[address] = {address, key, next, 0};
}
for (int i = head; i != -1; i = node[i].next){
node[i].inList = 1;
count++;
}
if (!count) printf("0 -1\n");
else{
sort(node, node+100001, cmp);
printf("%d %05d\n", count, node[0].address);
for (int i = 0; i < count - 1; i++) printf("%05d %d %05d\n", node[i].address, node[i].key, node[i+1].address);
printf("%05d %d %d\n", node[count-1].address, node[count-1].key, -1);
}
return 0;
}

1097 Deduplication on a Linked List (25)

题目思路

  • 读入静态链表结点数据,用一个 set 记录出现过的数字的绝对值
  • 扫描题目给出的链表结点
    • 若其数据域绝对值已经出现过,则放到 removed 容器中
    • 若未出现过,将数据域绝对值加入到集合中,结点放到 result 容器中
  • 先输出 result 容器,再输出 removed 容器
  • 注意!!! 容器的大小size()返回值为一个无符号数,无符号数运算后再比较十分危险
    • for (int i = 0; i < vector.size() - 1; i++ 改为 for (int i = 1; i < vector.size(); i++ 避开 size()-1
#include<iostream>
#include<cmath>
#include<set>
#include<vector>
using namespace std;
struct Node{
int address, data, next;
} node[100001];
int main()
{
int head, n, address, data, next;
scanf("%d%d", &head, &n);
for (int i = 0; i < n; i++){
scanf("%d%d%d", &address, &data, &next);
node[address] = {address, data, next};
}
vector<Node> result, removed;
set<int> occured;
for (int p = head; p != -1; p = node[p].next){
if (occured.find(abs(node[p].data)) != occured.end()) removed.push_back(node[p]);
else{
occured.insert(abs(node[p].data));
result.push_back(node[p]);
}
}
for (int i = 1; i < result.size(); i++)
printf("%05d %d %05d\n", result[i-1].address, result[i-1].data, result[i].address);
if (result.size() > 0) printf("%05d %d -1\n", result[result.size()-1].address, result[result.size()-1].data);
for (int i = 1; i < removed.size(); i++)
printf("%05d %d %05d\n", removed[i-1].address, removed[i-1].data, removed[i].address);
if (removed.size() > 0) printf("%05d %d -1\n", removed[removed.size()-1].address, removed[removed.size()-1].data);
return 0;
}

1133 Splitting A Linked List (25)

题目思路

  • 设置全局变量 K,在程序中接收输入,以便于 cmp 函数使用
  • 在结点中设置 oriorder 变量,记录其在原始链表中的顺序,以便于 cmp 函数使用
  • cmp 函数首先将不在链表中的放到数组后面,再看如果两个结点数值分别在 0 或 K 两侧,则按数值域排序,否则仍按原链表顺序
#include<iostream>
#include<algorithm>
using namespace std;
int K = 0;
struct Node{
int address, data, next, inList, oriorder;
} node[100001];
bool cmp (Node a, Node b){
if (!a.inList || !b.inList) return a.inList > b.inList;
if ((a.data >= 0 && b.data < 0) || (a.data < 0 && b.data >= 0)) return a.data < b.data;
if ((a.data > K && b.data <= K) || (a.data <= K && b.data > K)) return a.data < b.data;
return a.oriorder < b.oriorder;
}
int main()
{
int n, head, address, data, next, count = 0, order = 0;
scanf("%d%d%d", &head, &n, &K);
for (int i = 0; i < n; i++){
scanf("%d%d%d", &address, &data, &next);
node[address] = {address, data, next, 0, 0};
}
for (int p = head; p != -1; p = node[p].next){
node[p].inList = 1;
node[p].oriorder = order;
count++;
order++;
}
sort(node, node+100001, cmp);
for (int i = 0; i < count - 1; i++)
printf("%05d %d %05d\n", node[i].address, node[i].data, node[i+1].address);
printf("%05d %d %d\n", node[count-1].address, node[count-1].data, -1);
return 0;
}

二刷(参考柳婼小姐姐的代码

  • 遍历链表,先后选取 (-无穷,0), [0,k], (k,+无穷)压入 result 容器
  • 输出 result 中的结点即为所要求的顺序
#include<iostream>
#include<vector>
using namespace std;
struct Node{
int address, data, next;
} node[100000];
int main()
{
int head, n, k, address, data, next;
scanf("%d%d%d", &head, &n, &k);
for (int i = 0; i < n; i++){
scanf("%d%d%d", &address, &data, &next);
node[address] = {address, data, next};
}
vector<Node> result;
for (int p = head; p != -1; p = node[p].next)
if (node[p].data < 0) result.push_back(node[p]);
for (int p = head; p != -1; p = node[p].next)
if (node[p].data >= 0 && node[p].data <= k) result.push_back(node[p]);
for (int p = head; p != -1; p = node[p].next)
if (node[p].data > k) result.push_back(node[p]);
for (int i = 1; i < result.size(); i++)
printf("%05d %d %05d\n", result[i-1].address, result[i-1].data, result[i].address);
printf("%05d %d -1\n", result[result.size()-1].address, result[result.size()-1].data);
return 0;
}

附:

动态链表

  • 头结点:数据域不存放任何内容,指针域指向第一个数据域有内容的结点
  • 最后一个节点的指针域指向 NULL,表示链表结尾
(1) 创建链表
node *p, *pre, *head;
head = new node();
head->next = NULL;
pre = head;
for (int i = 0; i < n; i++){
p = new node;
p->data = data[i];
p->next = NULL;
pre->next = p;
pre = p;
}
(2) 查找元素
// 查找链表中 x 并记录个数
node *p = head->next;
while (p != NULL){
if (p->data == x){
count++;
}
p = p->next;
}
(3) 插入元素
// 将 x 插入链表第 pos 个位置
node *p = head;
for (int i = 0; i < pos-1; i++){
p = p->next;
}
node *q = new node;
q->data = x;
q->next = p->next;
p->next = q;
(4) 删除元素
// 删除链表中数据域为 x 的结点
node *p = head->next;
node *pre = head;
while (p != NULL){
if (p->data = x){
pre->next = p->next;
delete(p);
p = pre->next;
}
else{
pre = p;
p = p->next;
}
}

PAT甲级 链表题_C++题解的更多相关文章

  1. PAT甲级 排序题_C++题解

    排序题 PAT (Advanced Level) Practice 排序题 目录 <算法笔记> 6.9.6 sort()用法 <算法笔记> 4.1 排序题步骤 1012 The ...

  2. PAT甲级 模拟题_C++题解

    模拟题 PAT (Advanced Level) Practice 模拟题 目录 1008 Elevator (20) 1042 Shuffling Machine (20) 1046 Shortes ...

  3. 1080 Graduate Admission——PAT甲级真题

    1080 Graduate Admission--PAT甲级练习题 It is said that in 2013, there were about 100 graduate schools rea ...

  4. PAT甲级 Dijkstra 相关题_C++题解

    Dijkstra PAT (Advanced Level) Practice Dijkstra 相关题 目录 <算法笔记>重点摘要 1003 Emergency (25) <算法笔记 ...

  5. PAT甲级 进制转换题_C++题解

    进制转换题 PAT (Advanced Level) Practice 进制转换题 目录 <算法笔记> 重点摘要 1015 Reversible Primes (20) 1019 Gene ...

  6. PAT甲级 散列题_C++题解

    散列 PAT (Advanced Level) Practice 散列题 目录 <算法笔记> 重点摘要 1002 A+B for Polynomials (25) 1009 Product ...

  7. PAT甲级 二叉树 相关题_C++题解

    二叉树 PAT (Advanced Level) Practice 二叉树 相关题 目录 <算法笔记> 重点摘要 1020 Tree Traversals (25) 1086 Tree T ...

  8. PAT甲级 二叉查找树 相关题_C++题解

    二叉查找树 PAT (Advanced Level) Practice 二叉查找树 相关题 目录 <算法笔记> 重点摘要 1099 Build A Binary Search Tree ( ...

  9. PAT甲级 并查集 相关题_C++题解

    并查集 PAT (Advanced Level) Practice 并查集 相关题 <算法笔记> 重点摘要 1034 Head of a Gang (30) 1107 Social Clu ...

随机推荐

  1. 在JAVA中怎么比较Double类型数据的大小

    在JAVA中怎么比较Double类型数据的大小  我来答  浏览 33044 次   3个回答 #活动# “双11”答题活动,奖励加码!最高得2000元购物礼金! pollutedair 2015- ...

  2. Python: 在CSV文件中写入中文字符

    0.2 2016.09.26 11:28* 字数 216 阅读 8053评论 2喜欢 5 最近一段时间的学习中发现,Python基本和中文字符杠上了.如果能把各种编码问题解决了,基本上也算对Pytho ...

  3. ConsoleWebsocketServer服务端和ConsoleWebsocketClient客户端

    本文是简述了Websocket的服务端和客户端的实时通讯过程,Websocket的服务端和客户端的具体使用使用了2种Websocket的服务端和2种客户端. 以下代码使用的是Visual Studio ...

  4. Tensorflow 2 flower_photos花卉数据集手动下载、离线安装、本地加载、快速读取

    Tensorflow 2 flower_photos花卉数据集手动下载.离线安装.本地加载.快速读取 商务合作,科技咨询,版权转让:向日葵,135-4855__4328,xiexiaokui#qq.c ...

  5. python3 selenium模块Chrome设置代理ip的实现

    python3 selenium模块Chrome设置代理ip的实现 selenium模块Chrome设置代理ip的实现代码: from selenium import webdriver chrome ...

  6. [转]Android四大核心组件:Activity+Service+BroadcastReceiver+ContentProvider

    原文地址:http://c.biancheng.net/view/2918.html Android 作为一个移动设备的开发平台,其软件层次结构包含操作系统 (OS).中间件 (MiddleWare) ...

  7. Mac OS -bash: psql: command not found 使用 psql 命令报错

    使用 psql 在 mac os 系统上登录,系统显示没有 psql 这个命令存在 解决方法如下: 将 postgresql 的 bin 目录添加到环境变量中即可 export PATH=" ...

  8. Oracle中复制表的方法(create as select、insert into select、select into)

    转: Oracle中复制表的方法(create as select.insert into select.select into) 2018-07-30 22:10:37 小白白白又白cdllp 阅读 ...

  9. 算法习题---4-8特别困的学生(UVa12108)

    一:题目 课堂上有n个学生(n<=),每个学生上课都会出现一个“清醒-睡眠”周期,其中第i个学生学习Ai分钟后睡眠Bi分钟,依次重复.其中在从清醒到睡眠时有一个条件:只有到全班睡眠人数大于清醒人 ...

  10. Internet Download Manager 快速下载插件,破解版

    下载下来直接双击绿化按钮即可. 软件链接 : https://pan.baidu.com/s/1agK3cLtjJzXcGEgsuv5mVQ  提取码: ckm7