与链表有关的算法题

文章目录

  • [0. 注意](#0. 注意)
  • [1. 排队顺序(链表的打印)](#1. 排队顺序(链表的打印))
  • [2. 排队顺序(单链表)](#2. 排队顺序(单链表))
  • [3. 队列安排(双向链表)](#3. 队列安排(双向链表))
  • [4. 约瑟夫问题(循环链表)](#4. 约瑟夫问题(循环链表))

0. 注意

new 和 delete 是非常耗时的操作,

在算法比赛中,一般不会使用 new 和 delete 去模拟实现一个链表。

而 STL 里面的 list 的底层就是动态实现的双向循环链表,增删会涉及 new 和 delete,效率不高,竞赛中一般不会使用,而是以静态实现的方式。

关于链表的静态实现 可以参考我写的博客 点击转跳

1. 排队顺序(链表的打印)

https://www.luogu.com.cn/problem/B3630#ide

本题相当于告诉了我们每一个点的后继,使用静态链表的存储方式能够很好的还原这个队列。数组中 [1,n] 的下标可以当做数据域,根据题意修改指针域即可。

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;

int n,h,i;
const int N=1e6+10;

int main()
{
    cin>>n;
    int ne[N];
    for(i=1;i<=n;i++)
    {
        cin>>ne[i];
    }
    cin>>h;
    for(i=h; i;i=ne[i])
    {
        cout<< i <<" ";
    }
    return 0;
}

2. 排队顺序(单链表)

https://www.luogu.com.cn/problem/B3631

链表模板题,直接实现⼀个单链表即可!!

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;

int h, id;
const int N=1e6+10;
int e[N],ne[N],mp[N],q,op,x,y;


int main()
{
    id++;
    e[id]=1;
    ne[h]=1;
    mp[1]=id;
    cin>>q;
    for(int i=0;i<q;i++)
    {
        cin>>op>>x;
        if(op==1)
        {
            cin>>y;
            id++;
            e[id]=y;
            ne[id]=ne[mp[x]];
            ne[mp[x]]=id;
            mp[y]=id;
        }
        if(op==2)
        {     
            cout<<e[ne[mp[x]]]<<endl;
        }
        if(op==3)
        {
            if(ne[mp[x]])
            {
               // mp[e[ne[mp[x]]]]=0;
                ne[mp[x]]=ne[ne[mp[x]]];
            }
        }
    }
    return 0;
}

3. 队列安排(双向链表)

https://www.luogu.com.cn/problem/P1160

频繁的在某⼀个位置之前和之后插⼊元素,因此可以⽤双向循环的链表来模拟。

循环双链表的静态实现可以参考我的博客 点击转跳

cpp 复制代码
#include<bits/stdc++.h>

using namespace std;

const int N =1e5+10;

int h,id,k,p,M,x;

int ne[N],mp[N],pre[N];

int main()
{
    int num;
    ne[0]=1;
    pre[1]=0;
    mp[1]=1;
    id++;
    cin>>num;
    for(int i=2;i<=num ;i++)
    {
        cin>>k>>p;
        id++;
        mp[i]=id;
        if(p==1)
        {
           ne[id]=ne[k];
           pre[id]=mp[k];
           pre[ne[mp[k]]]=id;
           ne[mp[k]]=id; 
            
        }
        else
        {
           ne[id]=mp[k];
           pre[id]=pre[mp[k]];
           ne[pre[mp[k]]]=id;
           pre[mp[k]]=id ;
        }
    }
    
    cin>>M;
    while(M--)
    {
        cin>>x;
        if(mp[x])
        {

            ne[pre[mp[x]]]=ne[mp[x]];
            pre[ne[mp[x]]]=pre[mp[x]];
            mp[x]=0;
        }
    }

    for(int j = ne[h];j;j=ne[j])
    {
        cout<<j<<" ";
    }
    return 0;
}

4. 约瑟夫问题(循环链表)

https://www.luogu.com.cn/problem/P1996

使⽤循环链表模拟即可! 但是这里面有一些小细节 我们删除元素的时候 每走m-1次就删除后面的元素 (比如给的测试样例是每走3次删一个元素,我们每数2次就删除它后面的元素),这是因为单链表删除有个关键的步骤是 ne[删除元素的前一个元素的位置]=ne[ne[删除前一个元素的位置]]如果我们直接删除当前元素,就很难找到当前元素的前一个位置!

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
const int N =110;
int n,m;
int h,id;
int ne[N];

int main()
{
    cin>>n>>m;
    //创建循环链表
    for(int i=1;i<n;i++)
    {
        ne[i]=i+1;
    }
    ne[n]=1;

    //用t指针进程模拟
    int t=n;//从1开始报数,那么t初始位置就该在最后
    while(n--)
    {
        for(int i=1;i<m;i++)
        {
            t=ne[t];
        }
        cout<<ne[t]<<" ";
        ne[t]=ne[ne[t]];
    }
    return 0;
}
相关推荐
KerwinChou_CN1 小时前
LangGraph 快速入门
服务器·网络·算法
雨落在了我的手上2 小时前
C语言之数据结构初见篇(2):顺序表之通讯录的实现
数据结构
安之若素.re2 小时前
918. 环形子数组的最大和
算法
阿阿阿阿里郎2 小时前
ROS2快速入门--C++基础
开发语言·c++·算法
free-elcmacom2 小时前
C++<x>new和delete
开发语言·c++·算法
lxh01132 小时前
计算右侧小于当前元素的个数 题解
javascript·数据结构·算法
滴滴答滴答答2 小时前
机考刷题之 12 LeetCode 684 冗余的边
算法·leetcode·职场和发展
美式请加冰2 小时前
前缀数组的介绍和使用
数据结构·c++·算法
GawynKing2 小时前
图论2 图的数据结构表示
数据结构·图论