5.25

1.

学校老师要将班上 N 个同学排成一队,同学被编号为 1∼N,老师采取如下方法:

  1. 先将 1 号同学安排进队伍,这时队伍只有他一个人;
  2. 2∼N 号同学依次入队,编号为i的同学入队方式为:老师指定编号为i的同学站在编号为 1∼(i−1)中某位同学的右边;
  3. 从队伍中去掉 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。

  • 5
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值