数组模拟单链表,栈和队列
链表,栈和队列
在工程开发以及leetcode中,我们经常看到的实现链表的数据结构一般是结构体 或者类
class Node {
int data;
Node next;
}
但是在算法题中,这种做法并不可取,因为算法题喜欢把数据范围设置到极限,而且动态链表需要用到new这个关键字,速度会非常的慢 ,这样一般情况下都会超时。所以我们在算法题中常常使用数组来模拟链表,这样速度会很快。而且存储量不会这么大。
数组模拟链表的模板如下:
const int N = 100010;
int head,e[N],ne[N],idx;//所有idx表示的是节点的下标,也就是索引,然后当前idx的值表示下一个插入的节点的索引是多少,或者说当前插入新的节点用到的下标是多少,e[N]表示
void init(){
head = -1;//用-1来表示null
idx = 0;//下标也可以从1开始,无所谓
}
//头插法 ,在head后面插入一个节点值为x的节点
void add_to_head(int x){
e[idx] = x;
ne[idx] = head;
head = idx ++;
}
//在索引是k的下一个位置插入x ,如果知道第k的元素的索引 那么后面那个元素删除和插入操作复杂度都是O(1)
void add_after_k(int k,int x){
e[idx] = x;
ne[idx] = ne[k];
ne[k] = idx ++;
}
//删除在索引是k的下一个节点
void remove_after_k(int k){
ne[k] = ne[ne[k]];
}
//遍历一个单链表.固定模板
for(int i = head;i != -1;i ++) {
cout << e[i] << " ";
}
用数组模拟邻接表(图论模板的基础)
其实,邻接表就是多个链表的组合,有多个头节点,所以就需要一个头节点数组h[N],每个头节点延伸出的单链表就表示所有由这个节点为出发点连出的有向边,单链表中每个节点就表示当前这个头节点i 直接相连的节点,然后因为是一个单链表,肯定有e[M],e[M],idx三个要素。
const int N = 100010,M = 100010;//N 为最大节点数,M 为最大边数
int h[N],e[M],ne[M],w[M],idx;//
//加边操作模板
void add(int a,int b,int c){//加入一条从a----->b,而且权值为c,将其看作单链表的操作会更好理解
e[idx] = b;
ne[idx] = h[a];
w[idx] = c;
h[a] = idx ++;
}
用数组模拟双向链表
const int N= 100010;
int m;
int e[N],l[N],r[N],idx;
//双链表的的插入应该先把新节点的左右指向先赋值好,然后其他操作都用新界点的左右指向来操作,这样就会方便
//应该这样不会考虑原来的指向指针丢失的问题
void init(){//链表为空的初始化状态,head和tail可以用0 1来代表,所以idx 应该从2开始
r[0] = 1,l[1] = 0;
idx = 2;
}
//在第k个元素的右边插入一个新元素,若想在k的左边插入元素直接调用add(l[k],x)就可以,或者重新实现一编逻辑
void addR(int k,int x){
e[idx] = x;
l[idx] = k;
r[idx] = r[k];
l[r[idx]] = idx;
r[k] = idx ++;
}
void addL(int k,int x) {
e[idx] = x;
r[idx]= k;
l[idx] = l[k];
l[k] = idx;
r[l[idx]] = idx ++;
}
//删除双链表中的第k个元素
void remove_k(int k){
r[l[k]] = r[k];
l[r[k]] = l[k];
}
void add_to_begin(int x){
e[idx] = x;
r[idx] = r[0];
l[idx] = 0;
r[0] = idx;
l[r[idx]] = idx ++;
}
void add_to_last(int x) {
e[idx] = x;
l[idx] = l[1];
r[idx] = 1;
r[l[idx]] = idx;
l[1] = idx ++;
}
用数组模拟栈
const int N = 100010;
int stk[N],tt;//tt表示栈顶元素的索引,为0的时候表示没有元素
void push(int x){
stk[++ tt] = x;
}
//delete
void pop(){
tt --;//删除元素直接指针下移就行
}
int top(){
return stk[tt];
}
//判空
bool empty(){
if(tt > 0) return false;//tt不为0就表示栈不为空
return true;
}
用数组模拟队列
const int N = 100010;
int q[N];
int hh,tt = -1;//hh表示队头指针,tt表示队尾指针,最开始队列中一个元素都没有,所以队尾指针为-1.
void offer(int x){
q[ ++ tt] = x;//入队,队尾指针+1
}
void poll(){
hh ++;//出队,队头指针+1
}
bool empty(){
if(hh <= tt) return false;//判断队列是否为空
return true;
}