第二章 数据结构

826. 单链表

使用数组模拟链表,因为采用结构体+new的方式比较慢,笔试中一般不使用。单链表的用途是邻接表,邻接表的应用场景是存储树和图。

每一个结点存储val(结点值)以及next(指针,指向下个节点的地址),用eN数组来存储节点的值,neN数组来存储节点的next指针是多少,此外多定义一个head表示头指针的位置,一个idx表示当前已经用到了哪个点。eN和neN是通过下标关联起来。如图所示

对于插入操作,如将红色点插入到头结点的位置(头插法)

cpp 复制代码
void add_to_head(int x){
    e[idx] = x;
    ne[idx] = head;
    head = idx++;
}

将元素插入到下标为k的结点后面

cpp 复制代码
void add(int k, int x){
    e[idx] = x;
    ne[idx] = ne[k];
    ne[k] = idx++;
}

将下标为k的结点后面的结点删掉

cpp 复制代码
void remove(int k){
    ne[k] = ne[ne[k]];   
}

题目思路

  • 向链表头插入一个数
  • 删除第 k个插入的数后面的一个数
  • 在第 k个插入的数后插入一个数

c++ 代码

cpp 复制代码
#include<iostream>
using namespace std;
const int N = 100000;
int ne[N], e[N], head, idx;
//val[i]:表示结点i的值
//e[i]: 表示结点的下个节点的位置
//head:表示头指针的位置
//idx:表示当前已经用到了哪个点
void init(){
    head = -1;
    idx = 0;
}

//将x查到头结点
void add_to_head(int x){
    e[idx] = x;
    ne[idx] = head;
    head = idx++;
}
void add(int k, int x){
    e[idx] = x;
    ne[idx] = ne[k];
    ne[k] = idx++;
}
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 >> x;
            add(k - 1, x);
        }
    }
    // 将整个结点进行遍历
    for(int i = head; i != -1; i = ne[i]){
        cout << e[i] << ' ';
    }
    return 0;
}

827. 双链表

题目思路

双链表就是每一个结点有两个指针,一个指向前一个结点,一个指向后一个结点,用两个数组去表示,lN表示左边(前面)结点的下标,rN表示右边(后边)结点的下标。

这里规定,下标为0的点为头结点head,下标为1的点为尾结点tail,最开始的状态如下(初始化内容)

在k结点右边插入一个元素

cpp 复制代码
//在下标为k的点的右边插入x
void add(int k, int x){
    e[idx] = x;
    r[idx] = r[k];
    l[idx] = k;
    l[r[k]] = idx;//r[k]先调用,后修改
    r[k] = idx;
    
}

删除下标为k的结点

cpp 复制代码
void remove(int k){
    r[l[k]] = r[k];
    l[r[k]] = l[k];
}

c++代码

cpp 复制代码
#include<iostream>
using namespace std;
const int N = 100005;
int head, tail, r[N], l[N], e[N], idx, m;
void init(){
    r[0] = 1;
    l[1] = 0;
    idx = 2; // 0 ,1已经使用过了
}
//在下标为k的点的右边插入x
void add(int k, int x){
    e[idx] = x;
    r[idx] = r[k];
    l[idx] = k;
    l[r[k]] = idx;//r[k]先调用,后修改
    r[k] = idx++;
}
//在k的左边插入一个数等价于在k的左边结点(L[k])后插入一个数

//删除第k个点
void remove(int k){
    r[l[k]] = r[k];
    l[r[k]] = l[k];
}
int main(){
    cin >> m;
    init();
    while(m--){
        int k, x;
        string op;
        cin >> op;
        if(op == "L"){
            cin >> x;
            add(0, x);
        }else if(op == "R"){
            cin >> x;
            add(l[1], x);//tail结点的左侧
        }else if(op == "D"){
            cin >> k;
            remove(k + 1);
        }else if(op == "IL"){
            cin >> k >> x;
            add(l[k + 1], x);
        }else if(op == "IR"){
            cin >> k >> x;
            add(k  + 1, x);
        }
    }
    // 将整个表进行遍历
    for(int i = r[0]; i != 1; i = r[i]){
        cout << e[i] << " ";
    }
    return 0;
}

领接表

领接表是由多个单链表组成的,拿邻接表存储树和图放到第三章去讲。

相关推荐
CSharp精选营2 天前
关系型 vs 非关系型:从原理到选型,一文搞定数据库核心分类
数据结构·nosql·关系型数据库·非关系型数据库·技术选型
刘马想放假5 天前
Modbus 全栈技术解析:TCP、RTU、ASCII、RTU over TCP
数据结构·网络协议
北域码匠6 天前
冒泡排序太慢?鸡尾酒排序双向优化,原生 C# 零第三方库完整代码
数据结构·排序算法·泛型·c# 算法·鸡尾酒排序·原生 c# 开发·冒泡排序优化·嵌入式算法
Darling噜啦啦13 天前
列表转树算法深度解析:从 Map 到 Reduce 的两种实现,面试高频考点
数据结构·算法·面试
小小工匠14 天前
Redis - 事务机制:能实现 ACID 属性吗
数据结构·redis·性能优化·并发·持久化
玖玥拾14 天前
C/C++ 数据结构(七)栈、容器适配器
c语言·数据结构·c++··容器适配器
Qres82114 天前
算法复键——树状数组
数据结构·算法
牛油果子哥q14 天前
并查集(DSU)超精讲,路径压缩、按秩合并、万能模板、连通性判定、最小生成树与刷题实战全解
数据结构·c++·最小生成树·并查集
凌波粒14 天前
LeetCode--491.递增子序列(回溯算法)
数据结构·算法·leetcode
WL学习笔记14 天前
单项不带头不循环链表
数据结构·链表