电子学会六级-数据结构-链表
破损的键盘
https://www.luogu.com.cn/problem/UVA11988
#include<bits/stdc++.h>
const int N = 100000+5;
int last, cur, next[N];
char s[N];
int main(){
while(scanf("%s",s+1)==1){
int n=strlen(s+1);
last = cur = 0;
next[0] = 0;
for(int i = 1; i <= n; i++) {
char ch = s[i];
if(ch =='[') cur = 0;//遇到左括号 括号里面从0开始 放最前面
else if(ch==']') cur = last;//接在括号前面的字母后
else {
next[i] = next[cur];//记录前一个位置
next[cur] = i;//记录当前位置
if(cur == last) last = i;//出现左括号 cur和last不相等 出现胡括号后再次相等
cur = i;
}
}
for(int i = next[0]; i != 0; i = next[i])//从头指针 开始遍历
printf("%c", s[i]);
printf("\n");
}
return 0;
}
移动盒子
https://www.luogu.com.cn/problem/UVA12657
队列安排
https://www.luogu.com.cn/problem/P1160
构造双链表
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
struct node{
int L,R;
}a[100005];
int n, m;
//双向链表增加在右侧有节点
inline void addRight(int x, int pos) { //x号同学插入pos同学右边
a[x].L=pos;//x左指向pos
a[a[pos].R].L=x;//pos当前右q的左指向x --断掉当前pos的右的左
a[x].R=a[pos].R;//x的右指向pos的右 --断掉post的右
a[pos].R=x;//当前pos的右指向x
}
//双链表在左侧增加节点
inline void addLeft(int x,int pos) { //x号同学插入pos同学左边
a[x].R=pos;//x的右指向pos
a[a[pos].L].R=x;//pos的前一个的右指向x
a[x].L=a[pos].L;//x的左指向post的左
a[pos].L=x;//pos的左指向x
}
//双链表增加节点
inline void del(int x) {
if(a[x].L==-1) return;//如果左指针为-1 说明不存在此节点
a[a[x].L].R=a[x].R;//前面一个指向自己的下一个
a[a[x].R].L=a[x].L;//后面一个指向自己的前一个 27 28 断掉其他指向x的指针
a[x].L =-1;
a[x].R =-1;//29 30 这两行断掉x指向其他
}
//遍历输出
inline void output() {
int x = a[0].R;//从head 0开始
while(1) {
cout<<x<<" ";
if(a[x].R==-1) break;//右边为-1结束
x=a[x].R;
}
}
inline void init() {//构建链表
for(int i=1;i<=n;i++){
a[i].L=a[i].R=-1;
}
a[1].L=0;//队列初始化一个人 a[1]
a[0].R=1;
}
int main(){
scanf("%d", &n);//n个节点
int k,p;//k插入到哪个点的左面或者右面 p左面还是右面 0左面 1 右面
init();//初始双链表
for(int i=2; i<=n;i++){//从第2个同学开始插入
scanf("%d %d", &k,&p);//读入k p
if(!p) addLeft(i,k);//0 插入左面
else addRight(i,k);//1 插入右面
}
scanf("%d",&m);//读入m 删除前m个数
for(int i=1;i<=m;i++) {
scanf("%d",&k);
del(k);//删除
}
output();//遍历
return 0;
}
STL list
#include <bits/stdc++.h>
using namespace std;
bool vis[100005];
list<int> stus;//双向链表
list<int>::iterator pos[100005];//迭代器访问list
int main(){
int n;
scanf("%d",&n);//n个同学
stus.push_back(1);//list放入第一个元素
pos[1] = stus.begin();//获取开始位置迭代器
for (int i=2;i<=n;i++){
int k,p;
scanf("%d%d",&k,&p);//k插入到哪个点的左面或者右面 p左面还是右面 0左面 1 右面
if (p == 0){
pos[i] = stus.insert(pos[k],i);//在post[k]位置左面插入i
}else{
list<int>::iterator it = pos[k];
++it;
pos[i] = stus.insert(it,i);//在post[k]位置右面插入i
}
}
int m = 0;
scanf("%d",&m);//输入删除元素个数
for (int i=0;i<m;i++){
int x;
scanf("%d",&x);//需要移除的同学
if (!vis[x]){
stus.erase(pos[x]);
vis[x] = true;
}
}
for (list<int>::iterator i = stus.begin(); i != stus.end();i++){//迭代输出list
printf("%d ",*i);
}
return 0;
}
士兵队列训练问题
http://acm.hdu.edu.cn/showproblem.php?pid=1276
机器翻译
https://www.luogu.com.cn/problem/P1540
约瑟夫问题
https://www.luogu.com.cn/problem/P1996
循环链表
//循环链表实现。流程:数到这个人就把这个人从链表元素中删除并输出编号
#include<bits/stdc++.h>
using namespace std;
struct node{
int data;
node *next;
};
int n,m;
node *head,*p,*r;//head头指针 r尾指针 p当前指针
int main(){
scanf("%d %d",&n,&m);//输入n个人 数到m出列
if(m==0)m=n;//m为0 数到0就出等同与数到n
head=new node;//申请空间
head->data=1;//头节点数据置为1
head->next=NULL;//头节点下一个为空
r=head;//尾指针现在是头 头尾在一起
for(int i=2;i<=n;i++){
p=new node;
p->data=i;
p->next=NULL;
r->next=p;//把申请的新节点连到前面的链表上
r=p;//尾指针后移一个 尾插法
}
r->next=head;//尾指针指向头
r=head;//循环链表建立完成
for(int i=1;i<=n;i++){
for(int j=1;j<=m-2;j++)r=r->next;//循环到m的前两个人 方便后续删数据
cout<<r->next->data<<" ";//输出这第m个人的数据
r->next=r->next->next;//跳过这个节点
r=r->next;//新的一轮从上次的最后一个的下一个开始
}
return 0;
}
寄包柜
https://www.luogu.com.cn/problem/P3613
约瑟夫
https://www.luogu.com.cn/problem/P1145
循环数
https://www.luogu.com.cn/problem/P1467
作者:newcode 更多资源请关注纽扣编程微信公众号
从事机器人比赛、机器人等级考试、少儿scratch编程、信息学奥赛等研究学习