归并排序
基于比较排序渐进最优。稳定。
空间增长数量级:
N
N
N
求逆序对:用右指针 j
时:cnt += mid-i+1;
。记得清零。
void Merge (int*a, int l, int r) // [a+l, a+r]
{
static int aux[20];
if(l>=r) return;
int mid = (l+r)>>1;
merge(a, l,mid); merge(a, mid+1, r);
int i=l, j=mid+1;
for(int k=l; k<=r; k++) aux[k] = a[k];
for(int k=l; k<=r; k++)
{
if(i>mid) a[k]=aux[j++] , cnt+=mid-i+1;
else if(j>r) a[k]=aux[i++];
else if(a[i]<a[j]) a[k]=aux[i++];
else a[k]=aux[j++], cnt+=mid-i+1;
}
}
快速排序
原地排序。
空间增长数量级:
log
N
\log N
logN。
第
k
k
k 大数:统计比基准大的数量,只递归其中一半:
T
a
v
g
=
O
(
N
)
T_{avg}=\Omicron(N)
Tavg=O(N)
struct Quick
{
int p(int*a, int l, int r)
{
int b=a[l];
while(l<r)
{
while(l<r&&a[r]>b) r--; a[l]=a[r];
while(l<r&&a[l]<b) l++; a[r]=a[l];
} assert(l==r);
a[l]=b;
return l;
}
void s(int*a, int l, int r) // [a+l, a+r]
{
if(l>=r) return;
int m=p(a, l, r);
s(l, m-1);
s(m+1, r);
}
} quick_sort; //建议shuffle一下
算法改进1
- 使用Dijkstra的三向切分,甚至可达线性。
- 香农信息量告诉我们这是信息量最优的。
咕在红书 ↩︎