当前位置: 首页 > news >正文

2-8 单链表+双链表+模拟栈+模拟队列

今天给大家用数组来实现链表+栈和队列

单链表:

首先要明白是如何用数组实现,

在这里需要用到几个数组,head表示头节点的下标,e[i]表示表示下标为i的值,ne[i]表示当前节点下一个节点的下标。idx表示当前已经用到那个点来了。

接着就是实现,首先各个步骤的函数,首先初始化,对于头插,实质就是数组下标指向的转移,首先要把插入数存储,然后改变ne[i]就是把原来head所向的下标改成当前首元素所指向,然后呢就是把当前的下标让head指向,因为是头插,最后让idx++,为下一次插让位。

对于add,步骤其实和头插类似,都是先存储,然后让原来k的下一位置下标指向变为x的下一指向,然后把当前的idx让ne[k]指向

对于remove  删除,只需k的下一指向跳过一步,到k后第二个元素的指向即可。

#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
int e[N], ne[N], idx, head;
void Init()
{head = -1;idx = 0;
}
void int_to_head(int x)
{e[idx] = x;ne[idx] = head;head = idx;idx++;
}void add(int k,int x)
{e[idx] = x;ne[idx] = ne[k];ne[k] = idx;idx++;
}void remove(int k)
{ne[k] = ne[ne[k]];
}
int main() {int n;cin >> n;Init();//初始化for (int i = 0; i < n; i++) {char s;cin >> s;if (s == 'H') {int x;cin >> x;int_to_head(x);}if (s == 'D') {int k;cin >> k;if (k == 0) head = ne[head];//删除头节点else remove(k - 1);//注意删除第k个输入后面的数,那函数里放的是下标,k要减去1}if (s == 'I') {int k, x;cin >> k >> x;add(k - 1, x);//同样的,第k个数,和下标不同,所以要减1}}for (int i = head; i != -1; i = ne[i]) cout << e[i] << ' ';cout << endl;return 0;
}

双链表:

双链表和单链表类似,只不过有两个指针指向,

同时我们将0作为head,1作为tail,初始idx为2

#include<iostream>using namespace std;const int N = 1e5 + 10;int m;
int e[N], l[N], r[N];
int idx;//! 初始化
void init()
{l[1] = 0, r[0] = 1;//* 初始化 第一个点的右边是 1   第二个点的左边是 0idx = 2;//! idx 此时已经用掉两个点了
}//* 在第 K 个点右边插入一个 X 
void add(int k, int x)
{e[idx] = x;l[idx] = k;r[idx] = r[k]; //todo 这边的 k 不加 1 , 输入的时候 k+1 就好l[r[k]] = idx;r[k] = idx;idx++;
}//! 当然在 K 的左边插入一个数 可以再写一个 , 也可以直接调用我们这个函数,在 k 的左边插入一个 数 等价于在 l[k] 的右边插入一个数 add(l[k],x)//*删除第 k个 点
void remove(int k)
{r[l[k]] = r[k];l[r[k]] = l[k];
}int main(void)
{ios::sync_with_stdio(false);cin >> m;init();while (m--){string op;cin >> op;int k, x;if (op == "R"){cin >> x;add(l[1], x); //!   0和 1 只是代表 头和尾  所以   最右边插入 只要在  指向 1的 那个点的右边插入就可以了}else if (op == "L")//! 同理  最左边插入就是 在指向 0的数的左边插入就可以了   也就是可以直接在 0的 有右边插入{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;
}

就是什么意思呢,画个图模拟,

模拟栈:

先说一下什么栈
例如,你家放衣服的箱子中有n件衣服,你想要拿出第a件衣服,必须将它上面n-a件衣服拿走,才能将衣服取出来,所以我们可以分析出:栈是头进头出,栈尾是无法弹出元素的,同时栈无法随机访问任意元素

#include <iostream>
using namespace std;
const int N = 100010;
int st[N];
int top = -1;
int n;
int main()
{cin >> n;while(n--){string s;cin >> s;//栈顶所在索引往后移动一格,然后放入x。if(s == "push"){int a;cin >> a;st[++top] = a;}//往前移动一格if(s == "pop"){top --;}//返回栈顶元素if(s == "query"){cout << st[top] << endl;}//大于等于 0 栈非空,小于 0 栈空if(s == "empty"){cout << (top == -1 ? "YES" : "NO") << endl;}}
}

模拟队列:

就是一个特殊的数组。这个数组,最前面叫队头,最后面叫队尾。只允许在最后面添加元素,只允许在最前面删除元素

#include <iostream>
using namespace std;
const int N = 100010;
int q[N];//[hh, tt] 之间为队列(左闭右闭)
int hh = 0;//队头位置
int tt = -1;//队尾位置
//操作次数
int m;
//操作方式
string s;//入队:队尾先往后移动一格,再放入要插入的数据
void push(int x){q[++tt] = x;
}
//出队:队头往后移动一格
void pop(){hh++;
}
//[hh, tt]表示队列区间,当tt >= hh时,区间不为空
void empty(){if(tt >= hh) cout << "NO" << endl;else cout << "YES" << endl;
} 
//hh指向队头,q[hh]代表队头元素
void query (){cout << q[hh] << endl;
}int main(){cin >> m;while(m--){cin >> s;//入队if(s == "push"){int x;cin >> x;push(x);}//出队if(s == "pop"){pop();}//问空if(s == "empty"){empty();}//问队头if(s == "query"){query();}}
}

相关文章:

  • Vue-57、Vue技术路由的参数如何传递
  • vue3 可视化大屏自适应屏幕组件
  • error: object ‘FastMNNIntegration‘ not found
  • 159基于matlab的基于密度的噪声应用空间聚类(DBSCAN)算法对点进行聚类
  • 【echarts】入门示例
  • 基于微信小程序的新生报到系统的研究与实现,附源码
  • dolphinDB使用select筛选时间字段
  • PKI - 03 密钥管理(如何进行安全的公钥交换)
  • Bert与ChatGPT
  • Python程序员面试题精选及解析(2)
  • STM32F1 引脚重映射功能
  • Nginx访问控制模块详解
  • openkylin(Debian系)安装nginx及安装前需要的准备
  • 【计算机网络】协议层次及其服务模型
  • spring boot和spring cloud项目中配置文件application和bootstrap加载顺序
  • 2017 年终总结 —— 在路上
  • Android路由框架AnnoRouter:使用Java接口来定义路由跳转
  • C++类的相互关联
  • ES2017异步函数现已正式可用
  • Javascripit类型转换比较那点事儿,双等号(==)
  • JavaScript创建对象的四种方式
  • maven工程打包jar以及java jar命令的classpath使用
  • MySQL QA
  • text-decoration与color属性
  • 对JS继承的一点思考
  • 多线程事务回滚
  • 理解IaaS, PaaS, SaaS等云模型 (Cloud Models)
  • 两列自适应布局方案整理
  • 如何使用 OAuth 2.0 将 LinkedIn 集成入 iOS 应用
  • Spark2.4.0源码分析之WorldCount 默认shuffling并行度为200(九) ...
  • ​LeetCode解法汇总1276. 不浪费原料的汉堡制作方案
  • ​LeetCode解法汇总2696. 删除子串后的字符串最小长度
  • ​LeetCode解法汇总518. 零钱兑换 II
  • # Swust 12th acm 邀请赛# [ K ] 三角形判定 [题解]
  • #100天计划# 2013年9月29日
  • #pragma pack(1)
  • #免费 苹果M系芯片Macbook电脑MacOS使用Bash脚本写入(读写)NTFS硬盘教程
  • (31)对象的克隆
  • (附源码)springboot优课在线教学系统 毕业设计 081251
  • (经验分享)作为一名普通本科计算机专业学生,我大学四年到底走了多少弯路
  • (理论篇)httpmoudle和httphandler一览
  • .NET delegate 委托 、 Event 事件,接口回调
  • .NET LINQ 通常分 Syntax Query 和Syntax Method
  • .NET/C# 推荐一个我设计的缓存类型(适合缓存反射等耗性能的操作,附用法)
  • .NET设计模式(11):组合模式(Composite Pattern)
  • [ 常用工具篇 ] AntSword 蚁剑安装及使用详解
  • [].slice.call()将类数组转化为真正的数组
  • [BUG]vscode插件live server无法自动打开浏览器
  • [C#基础]说说lock到底锁谁?
  • [C++][数据结构][算法]单链式结构的深拷贝
  • [CF543A]/[CF544C]Writing Code
  • [CSS]浮动
  • [Docker]十一.Docker Swarm集群raft算法,Docker Swarm Web管理工具
  • [Flexbox] Using order to rearrange flexbox children
  • [Go WebSocket] 多房间的聊天室(五)用多个小锁代替大锁,提高效率