模拟单链表
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)