块状链表
使用前,请根据自己需要更改基本数据类型:
#define B_L_T int
以上实现了一个以 为基本数据类型的块状链表定义。
为了实现输出元素值的操作,使用前请根据需要更改输出方式 操作:
void put(B_L_T val){
printf("%d ",val);
}
变量
- :块数。
- :回收块内存。
- :元素数量。
- :块长,常为 。
- :块长限制系数,使块长不超过 ,一般设在 之间。
- :插入的数字。
- :空块。
- :第 个块:
-
- :指向前一个块。
-
- :指向后一个块。
-
- :块长。
-
- :块内第 个元素。
使用前要设定好 。
已经实现的操作
- :在第 个数之后插入 个数,这 个数应该提前存入内置数组 中,时间复杂度 。
- :删除从第 个数开始的 个数,超出部分不会改动,时间复杂度 。
- :输出第 到第 个数,常用于调试,时间复杂度 。
可用于扩展的基本操作
块状链表灵活多变,可以使用以下基本操作扩展到其他操作。
- :在 号块后新建一个节点,时间复杂度 。
- :删除 号块,块信息在被使用前不会改变,时间复杂度 。
- :得到第 个元素所在的块,并把 改成在块内的下标,时间复杂度 。
- :把第 块分裂成 和 ,第一块代替 ,第二块在 后面,时间复杂度 。
- :合并 块和 块,要保证这两个块都存在,也就是 和 非零,时间复杂度 。
#define B_L_T int
struct Block_List{
int tot,nc[N],size,len;
double max_len;
struct Block{
int head,next;
int len;
B_L_T b[2*N];
}a[N],e;
B_L_T add[M];
Block_List(){
tot=0;size=0;
e.head=e.next=0;
e.len=0;
max_len=2;
for(int i=1;i<N;i++)
nc[i]=i;
}
int build(int p){
int np=nc[++tot];
a[np]=e;
a[np].head=p;
a[np].next=a[p].next;
a[a[p].next].head=np;
a[p].next=np;
return np;
}
void del(int p){
nc[tot--]=p;
a[a[p].head].next=a[p].next;
a[a[p].next].head=a[p].head;
}
int get(int &p){
int kp=a[0].next;
for(;kp;kp=a[kp].next)
if(a[kp].len<p)
p-=a[kp].len;
else
break;
p--;
return kp;
}
void split(int p,int pos){
int np=build(p);
a[np].len=pos;
a[p].len-=a[np].len;
for(int i=0;i<a[np].len;i++)
a[np].b[i]=a[p].b[i+a[p].len];
}
void merge(int p){
for(int i=0;i<a[a[p].next].len;i++)
a[p].b[a[p].len+i]=a[a[p].next].b[i];
a[p].len+=a[a[p].next].len;
del(a[p].next);
}
void insert(int p,int n){
n--;
if(p>size)
return;
size+=n+1;
len=sqrt(size);
int kp=get(p),nkp;
if(p^(a[kp].len-1))
split(kp,p);
nkp=kp;
for(int i=0;i<n/len;i++){
nkp=build(nkp);
a[nkp].len=len;
for(int j=0;j<a[nkp].len;j++)
a[nkp].b[j]=add[j+i*len];
}
nkp=build(nkp);
a[nkp].len=n-n/len*len+1;
for(int i=n/len*len;i<=n;i++)
a[nkp].b[i-n/len*len]=add[i];
for(;nkp&&(!kp||nkp!=a[kp].head);nkp=a[nkp].head){
if(a[nkp].next&&a[nkp].len+a[a[nkp].next].len<max_len*len)
merge(nkp);
}
}
void remove(int p,int n){
if(p>size)
return;
int l=p,r=min(p+n-1,size);
size-=r-l+1;
len=sqrt(size);
int kl=get(l),kr=get(r);
if(l){
split(kl,l-1);
kl=a[kl].next;
}
if(r^(a[kr].len-1))
split(kr,r);
for(int k=kl;k^a[kr].next;k=a[k].next)
del(k);
if(a[kl].head&&a[kr].next&&a[a[kl].head].len+a[a[kr].next].len<max_len*len)
merge(a[kl].head);
}
void put(B_L_T val){
printf("%d ",val);
}
void write(int l,int r){
int lsl=l,lsr=r;
int kl=get(l),kr=get(r);
if(kl==kr){
for(int i=l;i<=r;i++)
put(a[kl].b[i]);
return;
}
write(lsl,lsl+a[kl].len-1-l);
for(int k=a[kl].next;k^kr;k=a[k].next)
for(int i=0;i<a[k].len;i++)
put(a[k].b[i]);
write(lsr-r,lsr);
}
}K;
本文作者:luckydrawbox
本文链接:https://www.cnblogs.com/luckydrawbox/p/18526591
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步