
static int N=100010;
//head存储链表头指针,e[]存储节点的值,ne[]存储节点的next指针,index表示当前用到了哪个节点
static int head,index;
static int []e=new int[N];
static int []ne=new int[N];
//链表初始化
static void init(){
head=-1;
index=0;
}
//头插法
static void add_head(int x){
e[index]=x;
ne[index]=head;
head=index++;
}
//将x插到下标为k的点的后面
static void add(int k,int x){
e[index]=x;
ne[index]=ne[k];
ne[k]=index;
index++;
}
//删除头节点,需要判断头节点存在
static void del_head(){
head=ne[head];
}
//将下标是k的点的后面的点删掉
static void del(int k){
ne[k]=ne[ne[k]];
}
//输出链表
for(int i=head;i!=-1;i=ne[i]){
System.out.print(e[i]+" ");
}
// e[]表示节点的值,l[]表示节点的左指针,r[]表示节点的右指针,index表示当前用到了哪个节点
static int head,index;
static int []e=new int[N];
static int []l=new int[N];
static int []r=new int[N];
//链表初始化
static void init(){
//0,1表示左边界和右边界,index = 2为下一个新节点的地址
r[0] = 1; l[1] = 0;
index = 2;
}
//在最左端插入x
static void insert_l(int x){
e[index]=x;
r[index]=r[0];
l[index]=0; //这个可不指,但反向遍历就需要,所以最好也指
l[r[0]]=index;
r[0]=index++;
}
//在最右端插入x
static void insert_r(int x){
//在右边界前插入时,新节点的右指针也要指向边界,否则无法遍历到边界(超时)
e[index]=x;
l[index]=l[1];
r[index]=1;
r[l[1]]=index;
l[1]=index++;
}
//在第 k 个插入的数后面插入一个数
static void insert_k(int k,int x){
e[index]=x;
l[index]=k;
r[index]=r[k];
l[r[k]]=index;
r[k]=index++;
}
//在第 k 个插入的数后面删除一个数
static void del(int k){
l[r[k]]=l[k];
r[l[k]]=r[k];
}特点:先进后出
static int N=100010;
static int []stk=new int[N];
static int tt=0; //tt表示栈顶
//向栈顶插入元素
stk[tt++]=x;
//从栈顶退出元素
tt--;
//栈顶元素
int top=stk[tt];
//判断栈是否为空
if(tt>0)特点:先进先出
// hh 表示队头,tt表示队尾
static int []q=new int[N];
static int hh = 0, tt = -1;
// 向队尾插入一个数
q[ ++ tt] = x;
// 从队头走出一个数
hh ++ ;
// 队头的值
q[hh];
// 判断队列是否为空
if (hh >tt) //队列为空模拟循环队列
// hh 表示队头,tt表示队尾的后一个位置
static int []q=new int[N];
static int hh = 0, tt = -1;
// 向队尾插入一个数
q[tt ++ ] = x;
if (tt == N) tt = 0;
// 从队头弹出一个数
hh ++ ;
if (hh == N) hh = 0;
// 队头的值
q[hh];
// 判断队列是否为空
if (hh != tt)