AcWing学习——链表

1. 单链表

单链表常用于写邻接表,而邻接表的主要应用是用于存储图和树。

算法题的c/c++中,new一块地址空间的操作非常慢,当我们需要对非常大的数据进行链表操作时,可以使用数组模拟链表,即静态操作。

邻接表就是把每个点的所有临边存下来。邻接表相当于多个单链表,每个单链表都用于存储当前元素所有的邻边元素。

1.1. 数组模拟邻接表

使用两个数组e[]ne[]分别存储链表元素和next下标,并且利用一个指针idx指向当前可用下标,初始为0。

当在第k+1个位置处插入一个节点时,都相当于在e[idx]处存储当前数值,而ne[idx]处存储ne[k]的值,而ne[k]处存储idx值。

当要将第k个位置的值删除时,仅需令ne[k]处修改为ne[ne[k]]即可,无需考虑内存泄露问题,因为算法题主要是为了快。

1.2. 例题

1.2.3.826. 单链表 -AcWing题库

c++ 复制代码
#include <iostream>

using namespace std;

const int N = 100010;

// head 表示头节点下标
// e[i] 表示节点i的值
// ne[i] 表示节点i的next指针是多少
// idx 存储当前已经用到了哪个点
int head, e[N], ne[N], idx;

//初始化
void init()
{
    head = -1;
    idx = 0;
}

// 头插法:将x插入头节点
void add_to_head(int x)
{
    e[idx] = x;
    ne[idx] = head;
    head = idx;
    idx++; 
}

// 将x插入下标为k的节点后面
void add(int k, int x)
{
    e[idx] = x;
    ne[idx] = ne[k];
    ne[k] = idx;
    idx++;
}

// 将下标为k的节点后面的节点删掉
void remove(int k)
{
    ne[k] = ne[ne[k]]; 
}

int main()
{
    int m;
    cin >> m;
    
    init();
    
    while(m --)
    {
        int k, x;
        char op;
        
        cin >> op;
        
        if(op == 'H')
        {
            cin >> x;
            add_to_head(x);
        }
        else if(op == 'D')
        {
            cin >> k;
            if(!k) head = ne[head];
            remove(k - 1);
        }
        else if(op == 'I')
        {
            cin >> k;
            cin >> x;
            add(k-1, x);
        }
    }
    
    for(int i = head; i != -1; i = ne[i]) cout << e[i] << " ";
    cout << endl;
    
    return 0;
}

2. 双链表

2.1. 数组模拟邻接表

使用三个数组e[]l[]r[]分别存储链表元素和当前元素的前一个元素下标和当前元素的后一个元素下标,并且利用一个指针idx指向当前可用下标,初始为0。

2.2. 例题

2.2.1.827.双链表 -AcWing题库

c++ 复制代码
#include <iostream>

using namespace std;

const int N = 100010;

int m;
int e[N], l[N], r[N], idx;

// 初始化
void init()
{
    // 使用0表示左端点,1表示右端点,
    // 因为0和1已经被使用了,idx从2开始
    r[0] = 1;
    l[1] = 0;
    idx = 2;
}

// 在下标为k的节点后面插入x
void add(int k, int x)
{
    e[idx] = x;
    l[idx] = k;
    r[idx] = r[k];
    l[r[k]] = idx;
    r[k] = idx;
    idx++;
}

// 删除下标为k的节点
void remove(int k)
{
    r[l[k]] = r[k];
    l[r[k]] = l[k];
}


int main()
{
    ios::sync_with_stdio(false);
    cin >> m;

    init();

    while(m--)
    {
        string op;
        cin >> op;
        int k, x;
        if(op=="R")
        {
            cin >> x;
            //!   0和 1 只是代表 头和尾  所以   最右边插入 只要在  指向 1的 那个点的右边插入就可以了
            add(l[1], x); 
        }
        //! 同理  最左边插入就是 在指向 0的数的左边插入就可以了   也就是可以直接在 0的 有右边插入
        else if(op=="L")
        {
            cin >> x;
            add(0, x);
        }
        else if(op=="D")
        {
            cin >> k;
            remove(k + 1);
        }
        else if(op=="IL")
        {
            cin >> k >> x;
            add(l[k + 1], x);
        }
        else
        {
            cin >> k >> x;
            add(k + 1, x);
        }    
    }
    for(int i = r[0]; i != 1; i = r[i]) cout << e[i] << ' ';
        
    return 0;
}
相关推荐
斯内科20 分钟前
四胞胎素数:找出‌个位数分别是 1、3、7、9‌,且‌十位及更高位数字完全相同‌的质数,例如 11、13、17、19
算法·质数·素数·四胞胎素数
Hello.Reader1 小时前
算法基础(十二)——主方法:快速求解常见递归式
算法
想唱rap1 小时前
传输层协议TCP
linux·运维·服务器·网络·c++·tcp/ip
小O的算法实验室1 小时前
2026年IEEE TITS,面向按需外卖配送调度的特定问题知识与基于学习元启发式算法,深度解析+性能实测
算法·论文复现·智能算法·智能算法改进
加勒比海带661 小时前
目标检测算法——农林行业数据集汇总附下载链接【Plant】
大数据·图像处理·人工智能·算法·目标检测
洛水水1 小时前
【力扣100题】23. 螺旋矩阵
算法·leetcode·矩阵
瑶池酒剑仙1 小时前
C++类和对象完全指南:从封装继承多态到内存布局的面向对象宝典(雨夜论道)
c语言·开发语言·c++·visual studio
影sir2 小时前
不同测试数据下,该如何选择算法
算法·深度优先
潇湘散客2 小时前
CAX软件插件化设计实现牛刀小试
c++·算法·图形学·opengl
Ricky_Theseus2 小时前
const 和 #define 的区别
c++