首页 > 其他分享 >平衡树总结

平衡树总结

时间:2024-12-23 16:21:36浏览次数:11  
标签:总结 rt ch return int prt rt1 平衡

从BST引入。

我们要高效查找一个值,那么在保证左儿子小于右儿子的二叉树上跳,期望\(O(d)\),\(d\)为深度。

二叉搜索树BST

最好\(O(\log n)\),最坏\(O(n)\)。

左子树的权值小于根的权值小于右子树的权值。

P用没有

替罪羊树

是一种依靠重构来维持平衡的重量平衡树。在插入删除时发现沿途失衡,就将当前子树暴力重构。

通过设置比例常数\(\alpha\in(0.5,1)\)来判断是否能重构。若当前节点的子节点的大小占它的大小的比例超过了\(\alpha\)。

另外由于采用惰性删除,只是计数器减一,以删除节点过多也会影响效率,所以当未被删除的节点个数占总大小的比例低于\(\alpha\)时,也要重构。

时间复杂度\(O(n\log n)\)。这种树的重构方式比起根号重构更优秀,在其他东西(比如带修的点分树)中也可以借鉴。

板子
#include<bits/stdc++.h>

using namespace std;

const int maxn=1e6+1e5+1;
const double alpha=0.8;
int lc[maxn],rc[maxn],val[maxn],w[maxn],s[maxn],siz[maxn],sd[maxn],ldr[maxn],sz,rt,n,m,last=0,ans=0,op,p,rnk,num,pre,sub;

inline void pushup(int k){
	s[k]=s[lc[k]]+s[rc[k]]+1;
	siz[k]=siz[lc[k]]+siz[rc[k]]+w[k];
	sd[k]=sd[lc[k]]+sd[rc[k]]+(w[k]!=0);
}

inline bool canreb(int k){
	return w[k]&&((double)max(s[lc[k]],s[rc[k]])>=alpha*s[k]||(double)sd[k]<=alpha*s[k]);
}

void rebfla(int &ldc,int k){
	if(!k) return;
	rebfla(ldc,lc[k]);
	if(w[k]) ldr[ldc++]=k;
	rebfla(ldc,rc[k]);
}

int rebuild(int l,int r){
	if(l>=r) return 0;
	int mid=(l+r)>>1;
	lc[ldr[mid]]=rebuild(l,mid);
	rc[ldr[mid]]=rebuild(mid+1,r);
	pushup(ldr[mid]);
	return ldr[mid];
}

void reb(int &k){
	int ldc=0;
	rebfla(ldc,k);
	k=rebuild(0,ldc);
}

void insert(int &k,int x){
	if(!k){
		k=++sz;
		if(!rt) rt=1;
		val[k]=x;
		lc[k]=rc[k]=0;
		w[k]=s[k]=siz[k]=sd[k]=1;
		return;
	}
	else{
		if(val[k]==x) w[k]++;
		else if(val[k]<x) insert(rc[k],x);
		else insert(lc[k],x);
		pushup(k);
		if(canreb(k)) reb(k);
	}
}

void del(int &k,int x){
	if(!k) return;
	else {
		if(val[k]==x){
			if(w[k]) w[k]--;
        }
		else{
			if(val[k]<x) del(rc[k],x);
			else del(lc[k],x);
		}
		pushup(k);
		if(canreb(k)) reb(k);
	}
}

int upper(int k,int x){
	if(!k) return 1;
	else if(val[k]==x&&w[k]) return siz[lc[k]]+w[k]+1;
	else if(val[k]<x) return siz[lc[k]]+w[k]+upper(rc[k],x);
	else return upper(lc[k],x);
}

int unupper(int k,int x){
	if(!k) return 0;
	else if(val[k]==x&&w[k]) return siz[lc[k]];
	else if(val[k]<x) return siz[lc[k]]+w[k]+unupper(rc[k],x);
	else return unupper(lc[k],x);
}

int querynum(int k,int x){
	if(!k) return 0;
	else if(siz[lc[k]]>=x) return querynum(lc[k],x);
	else if(siz[lc[k]]+w[k]<x) return querynum(rc[k],x-siz[lc[k]]-w[k]);
	else return val[k];
}

int querypre(int k,int x){
	return querynum(k,unupper(k,x));
}

int querysub(int k,int x){
	return querynum(k,upper(k,x));
}

int main(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;++i){
		scanf("%d",&p);
		insert(rt,p);
	}
	while(m--){
		scanf("%d%d",&op,&p);
		p=p^last;
		if(op==1) insert(rt,p);
		else if(op==2) del(rt,p);
		else if(op==3){
			rnk=unupper(rt,p)+1;
			last=rnk;
			ans^=rnk;
		}
		else if(op==4){
			num=querynum(rt,p);
			last=num;
			ans^=num;
		}
		else if(op==5){
			pre=querypre(rt,p);
			last=pre;
			ans^=pre;
		}
		else if(op==6){
			sub=querysub(rt,p);
			last=sub;
			ans^=sub;
		}
	}
	printf("%d\n",ans);
	return 0;
}

Treap

是一种弱平衡的二叉搜索树。同时符合堆和二叉搜索树的性质。

堆的权值为随机权值,以保证复杂度。

当堆的性质被破坏需要调整时,有旋Treap通过左旋或右旋来调整。FHQ-Treap在合并时使用随机赋的权值。

小根堆或者大根堆都行,都是为了复杂度正确。

注意到随机权值可以保证树高为\(\log n\)的,于是可以大胆做一些看似暴力实则正确的操作。

有旋Treap

板子
#include<bits/stdc++.h>
using namespace std;
const int maxn=100004;
int l[maxn],r[maxn],val[maxn],siz[maxn],rnd[maxn],w[maxn],sz,ans,rt,n,op,a;
inline void pushup(int k)
{
	siz[k]=siz[l[k]]+siz[r[k]]+w[k];
}
inline void rrotate(int &k)
{
	int t=l[k];
	l[k]=r[t];
	r[t]=k;
	siz[t]=siz[k];
	pushup(k);
	k=t;
}
inline void lrotate(int &k)
{
	int t=r[k];
	r[k]=l[t];
	l[t]=k;
	siz[t]=siz[k];
	pushup(k);
	k=t;
}
void insert(int &k,int x)
{
	if(!k)
	{
		++sz;
		k=sz;
		val[k]=x;
		siz[k]=1;
		w[k]=1;
		rnd[k]=rand();
		return;
	}
	siz[k]++;
	if(val[k]==x)
	{
		w[k]++;
	}
	else if(val[k]<x)
	{
		insert(r[k],x);
		if(rnd[r[k]]<rnd[k]) lrotate(k);
	}
	else
	{
		insert(l[k],x);
		if(rnd[l[k]]<rnd[k]) rrotate(k);
	}
}
bool del(int &k,int x)
{
	if(!k) return false;
	if(val[k]==x)
	{
		if(w[k]>1)
		{
			w[k]--;
			siz[k]--;
			return true;
		}
		if(l[k]==0||r[k]==0)
		{
			k=l[k]+r[k];
			return true;
		}
		else if(rnd[l[k]]<rnd[r[k]])
		{
			rrotate(k);
			return del(k,x);
		}
		else
		{
			lrotate(k);
			return del(k,x);
		}
	}
	else if(val[k]<x)
	{
		bool suc=del(r[k],x);
		if(suc) siz[k]--;
		return suc;
	}
	else
	{
		bool suc=del(l[k],x);
		if(suc) siz[k]--;
		return suc;
	}
}
int queryrank(int k,int x)
{
	if(!k) return 0;
	if(x==val[k])
	{
		return siz[l[k]]+1;
	}
	else if(x>val[k])
	{
		return siz[l[k]]+w[k]+queryrank(r[k],x);
	}
	else
	{
		return queryrank(l[k],x);
	}
}
int querynum(int k,int x)
{
	if(!k) return 0;
	else if(x<=siz[l[k]])
	{
		return querynum(l[k],x);
	}
	else if(x>siz[l[k]]+w[k])
	{
		return querynum(r[k],x-siz[l[k]]-w[k]);
	}
	else 
	{
		return val[k];
	}
}
void querypre(int k,int x)
{
	if(!k) return;
	else if(val[k]<x)
	{
		ans=k;
		querypre(r[k],x);
	}
	else querypre(l[k],x);
}
void querysub(int k,int x)
{
	if(!k) return;
	else if(val[k]>x)
	{
		ans=k;
		querysub(l[k],x);
	}
	else querysub(r[k],x);
}
int main()
{
	srand(1919810);
	scanf("%d",&n);
	while(n--)
	{
		scanf("%d%d",&op,&a);
		if(op==1)
		{
			insert(rt,a);
		}
		else if(op==2)
		{
			del(rt,a);
		}
		else if(op==3)
		{
			printf("%d\n",queryrank(rt,a));
		}
		else if(op==4)
		{
			printf("%d\n",querynum(rt,a));
		}
		else if(op==5)
		{
			ans=0;
			querypre(rt,a);
			printf("%d\n",val[ans]);
		}
		else if(op==6)
		{
			ans=0;
			querysub(rt,a);
			printf("%d\n",val[ans]);
		}
	}
	return 0;
}

无旋Treap(FHQ-Treap)

最重要的操作是分裂与合并。分裂通过引用\(l,r\)返回分裂出的两棵树的根,分为按值分裂(\(val\le x\)的在\(l\),其余在\(r\)),和按排名分裂(\(rk\le k\)的在\(l\),其余在\(r\))。合并通过引用返回合并后的根。

板子
#include<bits/stdc++.h>

using namespace std;

#define gc getchar
int rd(){
	int f=1,r=0;
	char ch=gc();
	while(!isdigit(ch)){ if(ch=='-') f=-1;ch=gc();}
	while(isdigit(ch)){ r=(r<<3)+(r<<1)+(ch^48);ch=gc();}
	return f*r;
} 

mt19937 rnd(19260817);

const int maxn=1e5+10;
int n,tot,rt,sz[maxn],rv[maxn],val[maxn],ch[2][maxn];

#define ls(k) (ch[0][k])
#define rs(k) (ch[1][k])

void pushup(int u){
	sz[u]=sz[ls(u)]+sz[rs(u)]+1;
}

int newnode(int v){
	sz[++tot]=1;
	rv[tot]=rnd();
	val[tot]=v;
	return tot;
}

void splitv(int u,int v,int &l,int &r){
	if(!u){
		l=r=0;
		return;
	}
	if(val[u]<=v) l=u,splitv(rs(u),v,rs(l),r);
	else r=u,splitv(ls(u),v,l,ls(r));
	pushup(u);
}

void splitsz(int u,int k,int &l,int &r){
	if(!u){
		l=r=0;
		return;
	}
	if(sz[ls(u)]+1<=k) l=u,splitsz(rs(u),k-sz[ls(u)]-1,rs(l),r);
	else r=u,splitsz(ls(u),k,l,ls(r));
	pushup(u);
}

void merge(int &u,int l,int r){
	if(!l||!r){
		u=l+r;
		if(u) pushup(u);
		return;
	}
	if(rv[l]>rv[r]) u=l,merge(rs(u),rs(l),r);
	else u=r,merge(ls(u),l,ls(r));
	pushup(u);
}

void insert(int x){
	int rtl=0;
	splitv(rt,x,rtl,rt);
	merge(rtl,rtl,newnode(x));
	merge(rt,rtl,rt);
}

void del(int x){
	int rt1=0;
	splitv(rt,x,rt1,rt);
	int rt2=0;
	splitv(rt1,x-1,rt2,rt1);
	int rt3=0;
	splitsz(rt1,1,rt3,rt1);
	merge(rt1,rt2,rt1);
	merge(rt,rt1,rt);
}

int qryrk(int x){
	int rt1=0;
	splitv(rt,x-1,rt1,rt);
	int rs=sz[rt1]+1;
	merge(rt,rt1,rt);
	return rs;
}

int qryval(int x){
	int rt1=0;
	splitsz(rt,x,rt1,rt);
	int rt2=0;
	splitsz(rt1,x-1,rt2,rt1);
	int rs=val[rt1];
	merge(rt1,rt2,rt1);
	merge(rt,rt1,rt);
	return rs;
}

int qrymx(int u){
	if(rs(u)) return qrymx(rs(u));
	return val[u];
}

int qrymi(int u){
	if(ls(u)) return qrymi(ls(u));
	return val[u];
}

int qrypre(int x){
	int rt1=0;
	splitv(rt,x-1,rt1,rt);
	int rs=qrymx(rt1);
	merge(rt,rt1,rt);
	return rs;
}

int qrysuf(int x){
	int rt1=0;
	splitv(rt,x,rt1,rt);
	int rs=qrymi(rt);
	merge(rt,rt1,rt);
	return rs;
}

void solve(){
	int op=rd(),x=rd();
	if(op==1) insert(x);
	else if(op==2) del(x);
	else if(op==3) printf("%d\n",qryrk(x));
	else if(op==4) printf("%d\n",qryval(x));
	else if(op==5) printf("%d\n",qrypre(x));
	else printf("%d\n",qrysuf(x));
	return;
}

int main(){
	n=rd();
	while(n--) solve(); 
	return 0;
}

FHQ-Treap更好写,可以持久化,结构更加灵活,这是相较于有旋Treap的优势。

Splay

时间复杂度靠均摊保证,每次操作后需要Splay()操作来保证时间复杂度,于是不太稳定,但很重要。可以说Splay的结构是平衡树中最灵活的,除了不能分裂合并。

板子
#include<bits/stdc++.h>

using namespace std;

const int maxn=1e5+10;
int n,m,sz=0,rt,a[maxn];
struct TREE{
	int val,siz,fa,ch[2],tag;
	inline void init(int _v,int _fa,int _siz,int _tag){
		val=_v,fa=_fa,siz=_siz,tag=_tag;
	}
}t[maxn];

inline void pushup(int k){
	t[k].siz=t[t[k].ch[0]].siz+t[t[k].ch[1]].siz+1; 
}

inline void pushdown(int k){
	if(t[k].tag){
		swap(t[k].ch[0],t[k].ch[1]);
		t[t[k].ch[0]].tag^=1;
		t[t[k].ch[1]].tag^=1;
		t[k].tag=0;
	}
} 

int build(int f,int l,int r){
	if(l>r) return 0;
	int mid=(l+r)>>1;
	int k=++sz;
	t[k].init(a[mid],f,1,0);
	t[k].ch[0]=build(k,l,mid-1);
	t[k].ch[1]=build(k,mid+1,r);
	pushup(k);
	return k;
}

inline void rotate(int x){
	int y=t[x].fa,z=t[y].fa,k=(t[y].ch[1]==x);
	t[x].fa=z,t[z].ch[(t[z].ch[1]==y)]=x;
	t[y].ch[k]=t[x].ch[k^1],t[t[x].ch[k^1]].fa=y;
	t[x].ch[k^1]=y,t[y].fa=x;
	pushup(y);
	pushup(x);
}

inline void splay(int x,int g){
	pushdown(x);
	if(!g) rt=x;
	while(t[x].fa!=g){
		int y=t[x].fa,z=t[y].fa;
		if(z!=g) (x==t[y].ch[0])^(y==t[z].ch[0])?rotate(x):rotate(y);
		rotate(x);
	}
}

inline int find(int x){
	int u=rt;
	if(!u) return -1;
	while(u){
		pushdown(u);
		if(t[t[u].ch[0]].siz+1==x){
			return u;
		}
		else if(t[t[u].ch[0]].siz>=x){
			u=t[u].ch[0];
		}
		else{
			x-=t[t[u].ch[0]].siz+1;
			u=t[u].ch[1];
		}
	}
	return -1;
}

void print(int u){
	pushdown(u);
	if(t[u].ch[0]) print(t[u].ch[0]);
	if(t[u].val>=1&&t[u].val<=n) printf("%d ",t[u].val);
	if(t[u].ch[1]) print(t[u].ch[1]);
}

int main(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n+2;++i) a[i]=i-1;
	rt=build(0,1,n+2);
	for(int i=1;i<=m;++i){
		int l,r;
		scanf("%d%d",&l,&r);
		l=find(l),r=find(r+2);
		splay(l,0),splay(r,l);
		t[t[r].ch[0]].tag^=1;
	}
	print(rt);
	return 0;
} 

可持久化平衡树(可持久化FHQ-Treap)

可持久化的思想都是一样的,把改变过的节点存下来以可持久化。

但是在平衡树里结构改变的地方太多了,FHQ稍微少一点但也很多。

splitvsplitszmergepushdown,以及打标记的时候都要可持久化。

特别的,如果不涉及从很久远的版本继承过来进行操作,而是和邻近的版本有关,但是有复制之类的操作时(这个东西在随机数据下是真的,刻意构造就假了),也需要可持久化。这时如果空间很紧,可以设置上限,达到后便线性地重构一下FHQ,释放一下废弃节点。

板子
#include<bits/stdc++.h>

using namespace std;

#define gc getchar
int rd(){
	int f=1,r=0;
	char ch=gc();
	while(!isdigit(ch)){ if(ch=='-') f=-1;ch=gc();}
	while(isdigit(ch)){ r=(r<<3)+(r<<1)+(ch^48);ch=gc();}
	return f*r;
}

mt19937 rnd(19260817);
const int maxn=5e5+10,inf=(1ll<<31)-1;
int n,tot,p,rt[maxn];
struct FHQ{
	int rv,val,sz,ch[2];
}t[maxn<<6];

#define ls(u) (t[u].ch[0])
#define rs(u) (t[u].ch[1])

void pushup(int u){
	t[u].sz=t[ls(u)].sz+t[rs(u)].sz+1;
}

int newnode(int v){
	t[++tot].sz=1;
	t[tot].rv=rnd();
	t[tot].val=v;
	return tot;
}

void splitv(int u,int v,int &l,int &r){
	if(!u){
		l=r=0;
		return;
	}
	if(t[u].val<=v){
		l=++tot;
		t[l]=t[u];
		splitv(rs(u),v,rs(l),r);
		pushup(l);
	}
	else{
		r=++tot;
		t[r]=t[u];
		splitv(ls(u),v,l,ls(r));
		pushup(r);
	}
}

void splitsz(int u,int k,int &l,int &r){
	if(!u){
		l=r=0;
		return;
	}
	if(t[ls(u)].sz+1<=k){
		l=++tot;
		t[l]=t[u];
		splitsz(rs(u),k-t[ls(u)].sz-1,rs(l),r);
		pushup(l);
	}
	else{
		r=++tot;
		t[r]=t[u];
		splitsz(ls(u),k,l,ls(r));
		pushup(r);
	}
}

void merge(int &u,int l,int r){
	if(!l||!r){
		u=l+r;
		if(u) pushup(u);
		return;
	}
	u=++tot;
	if(t[l].rv>t[r].rv){
		t[u]=t[l];
		merge(rs(u),rs(l),r);
	}
	else{
		t[u]=t[r];
		merge(ls(u),l,ls(r));
	}
	pushup(u);
}

void insert(int x,int &prt){
	int rt1=0;
	splitv(prt,x,prt,rt1);
	merge(prt,prt,newnode(x));
	merge(prt,prt,rt1);
}

void del(int x,int &prt){
	int rt1=0;
	splitv(prt,x,rt1,prt);
	int rt2=0;
	splitv(rt1,x-1,rt2,rt1);
	if(t[rt1].sz) merge(rt1,ls(rt1),rs(rt1));
	merge(rt1,rt2,rt1);
	merge(prt,rt1,prt);
}

int qryrk(int x,int &prt){
	int rt1=0;
	splitv(prt,x-1,rt1,prt);
	int rs=t[rt1].sz+1;
	merge(prt,rt1,prt);
	return rs;
}

int qrymx(int u){
	if(rs(u)) return qrymx(rs(u));
	return t[u].val;
}

int qrymi(int u){
	if(ls(u)) return qrymi(ls(u));
	return t[u].val;
}

int qryval(int x,int &prt){
	int rt1=0;
	splitsz(prt,x,rt1,prt);
	int rs=qrymx(rt1);
	merge(prt,rt1,prt);
	return rs;
}

int qrypre(int x,int &prt){
	int rt1=0;
	splitv(prt,x-1,rt1,prt);
	int rs=t[rt1].sz?qrymx(rt1):-inf;
	merge(prt,rt1,prt);
	return rs;
}

int qrysuf(int x,int &prt){
	int rt1=0;
	splitv(prt,x,prt,rt1);
	int rs=t[rt1].sz?qrymi(rt1):inf;
	merge(prt,prt,rt1);
	return rs;
}

void solve(){
	int v=rd(),op=rd(),x=rd();
	rt[++p]=rt[v];
	if(op==1) insert(x,rt[p]);
	else if(op==2) del(x,rt[p]);
	else if(op==3) printf("%d\n",qryrk(x,rt[p]));
	else if(op==4) printf("%d\n",qryval(x,rt[p]));
	else if(op==5) printf("%d\n",qrypre(x,rt[p]));
	else printf("%d\n",qrysuf(x,rt[p]));
}

int main(){
	n=rd();
	while(n--) solve();
	return 0;
}

标签:总结,rt,ch,return,int,prt,rt1,平衡
From: https://www.cnblogs.com/EmilyDavid/p/18624312

相关文章

  • 链剖分总结
    来解决树上DS问题。因为没有能够直接高效维护树型结构的DS,于是把树剖分成链,然后拿序列上的DS去维护每一条链的信息。树链剖分有很多种:轻重链剖分,长链剖分,虚实链剖分。轻重链剖分这里是轻重链剖分。常数很小。其实不一定要用线段树维护,但用线段树维护是最常见的。支持换根,路......
  • 鸿蒙Next ArkTS编程规范总结
    一、目标和适用范围ArkTS编程规范参考业界标准及实践,结合ArkTS语言特点,旨在提高代码的规范、安全和性能,适用于开发者使用ArkTS编写代码的系统开发或应用开发场景。二、规则来源ArkTS在TypeScript基础上强化静态检查和分析,部分规则源于《OpenHarmony应用TS&JS编程指南》,并为ArkT......
  • 79.尚庭公寓项目总结收获
    单体项目技术来自尚硅谷:https://www.bilibili.com/video/BV1At421K7gP/?spm_id_from=333.337.search-card.all.click&vd_source=eb2341710c995d8261ecc99fdd066ba71.Typora的使用用的其实就跟博客园写记一样的markdown形式但我是习惯于win自带的记事本或是直接博客园但是......
  • 大语言模型学习工具及资源总结和落地应用
            当前,随着人工智能技术的迅猛发展,大语言模型(LargeLanguageModels,LLMs)在各个领域的应用日益广泛。以下是国内外常见的大语言模型工具、已经落地部署的应用以及学习相关的网站和资源的详细介绍。一、国内外常见的大语言模型工具国际大语言模型1.OpenAIGPT......
  • 【社工钓鱼】手法总结
    一、rlo文件名翻转简介:全名Right-to-LeftOverride,本质是一串Unicode字符,编码0x202E,本身不可见,插入之后会让在他之后的字符串从右往左重新排列,本意是用来支持一些从右往左写的语言的文字,比如阿拉伯语、希伯来语等,现可以用来伪造文件名后缀,结合上一些其他手段可用作钓鱼文件的制作......
  • 【安全运维】监控告警要点总结
    前言监控告警是业务稳定性建设非常重要的一环,告警项的配置、告警阈值的设置、告警信息的发送和响应,都影响着业务稳定性。随着系统版本迭代,监控告警工具的变更,人员的变动等诸多因素的变化,我们需要定期对监控告警的方方面面做复盘,不断优化提升监控告警,以最大程度保障业务稳定。202......
  • AI工具类总结(二),门槛低,简单易上手!
    SWE-agent:SWE-agent接受GitHub问题并尝试使用GPT-4或您选择的LM自动修复它。它还可以用于进攻性网络安全或竞争性编码挑战。Chat2DB:AI驱动的数据库工具和SQL客户端,最热门的GUI客户端,支持MySQL、Oracle、PostgreSQL、DB2、SQLServer、DB2、SQLite、H2、ClickHous......
  • 2-SAT总结
    基础部分有K-Satisfiability问题,但\(k\ge2\)时那是NPC的,\(k=1\)时是trivial的,所以讨论2-Satisfiability。问题是这样的:\(n\)个bool变量,\(m\)个限制条件,每个限制会给出对于两个bool变量之间关系的描述,如\(a_i\lora_j\)为真。求一组可行解。显然我们可以暴搜,这里不说了。我们......
  • Linux常用命令总结
    du-sh*:用于显示当前目录下每个文件和子目录的大小。以下是这个命令中各个部分的作用:du:代表"diskusage"(磁盘使用情况),用于估算文件和目录所占用的磁盘空间。-s:代表"summarize"(汇总),用于显示每个指定文件或目录的总大小,而不是每个文件的详细信息。-h:代表"human-readable"(......
  • mysql log两个参数总结
    摘录:https://developer.baidu.com/article/details/3279159在MySQL的InnoDB存储引擎中,有两个与日志相关的参数非常重要,分别是innodb_log_buffer_size和innodb_log_file_size。这两个参数对InnoDB的性能和可靠性都有很大的影响。下面我们将详细解释这两个参数的含义、如何调整它们......