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;
}
相关推荐
电鱼智能的电小鱼几秒前
基于电鱼 AI 工控机的智慧工地视频智能分析方案——边缘端AI检测,实现无人值守下的实时安全预警
网络·人工智能·嵌入式硬件·算法·安全·音视频
孫治AllenSun33 分钟前
【算法】图相关算法和递归
windows·python·算法
格图素书1 小时前
数学建模算法案例精讲500篇-【数学建模】DBSCAN聚类算法
算法·数据挖掘·聚类
我是李武涯2 小时前
从`std::mutex`到`std::lock_guard`与`std::unique_lock`的演进之路
开发语言·c++
DashVector2 小时前
向量检索服务 DashVector产品计费
数据库·数据仓库·人工智能·算法·向量检索
AI纪元故事会2 小时前
【计算机视觉目标检测算法对比:R-CNN、YOLO与SSD全面解析】
人工智能·算法·目标检测·计算机视觉
夏鹏今天学习了吗3 小时前
【LeetCode热题100(59/100)】分割回文串
算法·leetcode·深度优先
卡提西亚3 小时前
C++笔记-10-循环语句
c++·笔记·算法
还是码字踏实3 小时前
基础数据结构之数组的双指针技巧之对撞指针(两端向中间):三数之和(LeetCode 15 中等题)
数据结构·算法·leetcode·双指针·对撞指针
亮剑20183 小时前
第1节:C语言初体验——环境、结构与基本数据类型
c++