1.
学校老师要将班上 N 个同学排成一队,同学被编号为 1∼N,老师采取如下方法:
- 先将 1 号同学安排进队伍,这时队伍只有他一个人;
- 2∼N 号同学依次入队,编号为i的同学入队方式为:老师指定编号为i的同学站在编号为 1∼(i−1)中某位同学的右边;
- 从队伍中去掉 m 个同学,其他同学位置顺序不变。
输入描述
第 1 行一个整数 N,表示有 N 个同学。
第 2∼N 行,第 i 行包含一个整数 k,表示将 i 号同学插入到 k 号同学右边。
第 N+1 行,一个整数 M,表示去掉的同学数目。
接下来 M 行,每行一个整数 x,表示将 x 号学生从队伍中移去,如果 x 号同学已经不在队列中,则忽略这一条指令。
输出描述
一行,空格隔开的若干个整数,表示队伍从左到右所有同学的编号。
#include <iostream>
typedef long long Int;
constexpr Int MAXN = 1000; // 最大的同学数目
Int N;
Int M;
struct Node { // 定义一个结构体 Node
Int x; // 定义一个长整型 x,表示同学编号
bool shan; // 定义一个布尔型 shan,表示是否被删除
Node* next; // 定义一个 Node 指针 next,表示下一个节点的指针
};
Node student[1+MAXN];
int main() {
std::cin >> N;
for(Int xh=1;xh<=N;xh++)
student[xh]=Node{xh,false,nullptr}; // 初始化同学队列
for(Int i=2;i<=N;i++){
Int k;
std::cin>>k; // 输入同学编号
student[i].next=student[k].next; // 将当前同学的下一个同学指向 k号 同学的下一个同学
student[k].next =student+i; // 将 k号 同学的下一个同学指向当前同学
}
std::cin>>M;
for(Int _=1;_<=M;_++){
Int x;std::cin>>x;
student[x].shan=true; // 将输入的要去掉大同学标记为已删除
}
for (Node *p = student+1; p; p = p->next)
if (!p->shan) { // 如果该同学没有被删除,那么他就是剩下的,输出他的编号
std::cout << p-student<< ' ';
}
std::cout << std::endl;
return 0;
}
2.
题目描述
实现一个数据结构,维护一张表(最初只有一个元素 11)。需要支持下面的操作,其中 𝑥x 和 𝑦y 都是 11 到 106106 范围内的正整数,且保证任何时间表中所有数字均不相同,操作数量不多于 105105:
1 x y
:将元素 𝑦y 插入到 𝑥x 后面;2 x
:询问 𝑥x 后面的元素是什么。如果 𝑥x 是最后一个元素,则输出 00;3 x
:从表中删除元素 𝑥x 后面的那个元素,不改变其他元素的先后顺序。
输入格式
第一行一个整数 𝑞q 表示操作次数。
接下来 𝑞q 行,每行表示一次操作,操作具体间题目描述。
输出格式
对于每个操作 2,输出一个数字,用换行隔开。
#include <iostream>
typedef long long Int;
constexpr Int MAX_N = 1000000;
struct Node {
Int x;
Node* next;
};
//定义一个指针数组,用于存储每个元素对应的节点
Node* zainali[1 + MAX_N];
//操作1
void caozuo1(Int x, Int y) {
Node* p = zainali[x];
//在x节点后插入y节点
zainali[y] = p->next = new Node{y, p->next};
}
//操作2
void caozuo2(Int x) {
Node* p = zainali[x];
//如果x节点后面没有节点,则输出0
if (!p->next) {
std::cout << "0" << std::endl;
} else {
//输出x节点后面的节点
std::cout << p->next->x << std::endl;
}
}
//操作3
void caozuo3(Int x) {
//获取x对应的节点
Node* p = zainali[x];
//获取x节点后面的节点
Node* q = p->next;
//将x节点指向后面的节点
p->next = q->next;
//删除后面的节点
delete q;
}
int main() {
Int q, a, b, c;
//创建链表头
Node* head = new Node{1, nullptr};
//将1号元素对应的节点指向头节点
zainali[1] = head;
std::cin >> q;
while (q >= 1) {
std::cin >> a;
if (a == 1) {
std::cin >> b >> c;
caozuo1(b, c);
} else if (a == 2) {
std::cin >> b;
caozuo2(b);
} else if (a == 3) {
std::cin >> b;
caozuo3(b);
}
q--;
}
}
知识:
继续讲链表,
循环链表:
就是这样,最后一个连着第一个,没有nullptr。
双向链表:
两个节点之间有两条线,一条是左边的指针,一条是右边的指针。
所以节点的结构体应该怎么写:
struct Node{
Node right;//指后面的节点
Node left;//指前面的节点
};//给双向链表一个指针,它可以删掉它然后再接上,单向链表不行。
循环双向链表:
两个节点之间有两条线,一条是左边的指针,一条是右边的指针,最后一个也连着第一个,没有nullptr。