基础数据结构
- 栈:
- 队列
- 单链表
- 双链表
1.栈
#include <bits/stdc++.h>
using namespace std;
const innt N = 1e6 + 10;
//栈 stk -->数组模拟栈 tt--> 栈顶
int stk[N], tt ;
//进栈
void push(int x){
if(tt + 1 > N) printf("overfloor\n");//栈溢出
else stk[++ tt] = x;
}
//判断栈空
void empty(){
if(tt > 0) printf("not empty");
else printf("empty");
}
//出栈
void pop(){
if( !tt ) printf("no position\n");// 栈空
else stk[tt--] = 0 ;//把弹出去的栈赋值 0
}
栈顶元素:
stk[tt];
单调栈常用问题:
给定一个序列,每一个数离她最近大的数字或者最小的数在什么地方。
例题
2. 队列
#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 10 ;
//队列
// q --> 队列 l --> 队头 r --> 队尾
int q[N], l, r;
//插入
void insert(int x){
q[++r] = x;
}
//弹出
void remove(){ l++;}
// 判断是否为空
void empty(){
if(l <= r ) printf("not empty\n");
else printf("empty\n");
}
队头:q[l];
队尾:q[r];
3.单链表
数组模拟链表:
#include <bits/stdc++.h>
using namespace std;
const int N = 1e7 + 10;
// 0 号点 e[0] 指针 ne[0] = 1
int head, e[N], ne[N], idx;
//head --> 头结点下标
// e[i] --> 表示节点 i的值
// ne[i] --> 表示节点 i 的next指针
// idx --> 存储当前用到的地址,相当于指针,当前用到的点
// 不论每次删除还是插入 idx++ 不用去管那些删除的空间(追求速度)
//初始化
void init(){
head = - 1;//头结点
idx = 0 ;
}
//将 x 插入到头结点后面
void add_to_head(int x){
e[idx] = x, ne[idx] = head, head = idx++;
}
//将 x 插入到下标是 k 的点后面
void add(int k,int x){
e[idx] = x, ne[idx] = ne[k], ne[k] = idx++;// == ne[k] = idx, idx++;
}
//删除下标是 k 的点后面一个点删掉
void remove(int k){
ne[k] = ne[ne[k]];
}
int main(){
int m;cin>>m;
init();//初始化
while(m--){
char op ;
int k , x;
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);//k 从 0 开始 所以要 - 1
}
else{
cin>>k >> x;
add(k - 1 , x);
}
// for(int i = head; i != -1; i = ne[i]) cout<<e[i]<<' ';cout<<endl;
}
//输出
for(int i = head; i != -1; i = ne[i]) printf("%d ",e[i]);
return 0;
}
4.双链表
//注 : 下面操作是 k + 1 ,原因是因为 idx == 1的情况初始化的时候已经使用了
#include <iostream>
#include <cstdio>
using namespace std;
const int N = 1e5 + 9;
int list[N], l[N], r[N], idx;
void init(){
r[0] = 1, l[1] = 0, idx = 2; //初始化头结点(右边指向第一个节点)和第一个节点(左边指向头结点)
}
// x 插到 k 后面
void insert(int k, int x){
list[idx] = x; //建立新节点
l[idx] = k; //将新节点连边
r[idx] = r[k]; //右边连接到下一个节点的左边,左边连接到上一个节点的右边
l[r[k]] = idx; //将原来两个相连接打的节点打断,连到新节点上
r[k] = idx; //右边的左指针连接到新节点的右指针上,左边同理
idx++; //位置加一
}
//删除第 x 个节点
void remove(int x){
r[l[x]] = r[x];
l[r[x]] = l[x];
}
int main(){
int m ;
init();
scanf("%d",&m);
while(m--){
string op;
int k,x;
cin>>op;
if(op == "L"){ //在链表的最左端插入 x 也就是在左边界后插入一个节点,就是最左端插入一个节点
scanf("%d",&x);
insert(0, x);
}
else if(op == "R"){ //在链表的最右端插入也,就是右边界的左节点后插入一个新节点
scanf("%d",&x);
insert(l[1], x);
}
else if(op == "IL"){ //第k个插入的数左侧插入一个数 在第k个插入的数的左节点后插入一个数
scanf("%d%d",&k,&x);
insert(l[k+1], x);
}
else if(op == "IR"){ //第k个插入的数右侧插入一个数
scanf("%d%d",&k,&x);
insert(k+1, x);
}
else if(op == "D"){ //把第k个插入的数删除
scanf("%d",&x);
remove(x+1);
}
}
for(int i = r[0]; i != 1; i = r[i]) printf("%d ",list[i]);
return 0;
}
注:OI蒻驹一枚,文章仅代表个人观点,如有不对,敬请指出,共同进步,谢谢。

浙公网安备 33010602011771号