Loading

排序

<目录

排序 \(\sf\small\color{gray}Sorting\)

排序,一个普遍的生活中的需求。
什么时候要排序?
你在年级上排第几名?
你怎么知道的?
把所有的人的成绩都按从大到小排一遍。
但,怎么排呢?

前置函数

交换函数那还是要的。
需要对变量交换和对指针交换两种 Swap()

void Swap(int&a,int&b)
{
	const int c=a;
	a=b,b=c;
	return;
}
void Swap(int*a,int*b)
{
	const int c=*a;
	*a=*b,*b=c;
	return;
}

桶排序 \(\sf\small\color{CCCCCC}Bucket\)

我搬出一排桶,编号以后把对应的元素扔进对应的桶。
最后按照桶的顺序把元素拿出来,不就有序了?
我们用数组模拟桶。

void BucketSort(int*a,int size)
{
	int maxi=0;
	for(int i=0;i<size;i++)
		if(a[i]>a[maxi])
			maxi=i;
	int A[maxi+10]={0},G=0;
	for(int i=0;i<size;i++)
		A[a[i]]++;
	for(int i=0;i<maxi;i++)
		while(A[i]--)
			a[G++]=i;
	delete []A;
	return;
}

该算法的最大缺点是,你数字越大,空间越多。

10000000000 1

这样一组数据轻轻松松卡死。
但是他却是所有排序中时间复杂度最低的……

选择排序 \(\sf\small\color{CCCCCC}Selection\)

只要我每次找出 最大/最小 的元素,排在最前面,不就好了么?
说得好,我们来实现它。

void IncertionSort(int*a,int size)
{
	for(int i=0;i<size;i++)
	{
		int minj=i;
		for(int j=i;j<size;j++)
			if(a[j]<a[minj])
				minj=j;
		Swap(a[i],a[minj]);
	}
	return;
}

这是一个基于比较的排序算法。

冒泡排序 \(\sf\small\color{CCCCCC}Bubble\)

我使劲遍历数组,只要先面的比后面的大,我们就交换他们。
遍历几遍呢?
答案是 n-1 遍。

经过 i 次扫描后,数列的末尾 i 项必然是最大的 项,因此冒泡排序最多需要扫描 n-1 遍数组就能完成排序。
\(\hspace{5cm}\)——OI Wiki

如果这次遍历没有交换元素,就说明数组已经有序了。

void BubbleSort(int*a,int size)
{
	for(int i=0;i<size-1;i++)
	{
		bool finish=true;
		for(int j=0;j<size-1;j++)
			if(a[j]>a[j+1])
				Swap(a[j],a[j+1]),
				finish=false;
		if(finish)	break;
	}
	return;
}

插入排序 \(\sf\small\color{CCCCCC}Insertion\)

扑克打过吗?
摸牌时,你摸出一张牌,看他在哪两个之间,然后插入。
这就是插入排序。

void InsertionSort(int*a,int size)
{
	for(int i=1;i<size;i++)
	{
		const int o=a[i];
		int j=i-1;
		while(j>=0&&a[j]>o)
			a[j+1]=a[j],j--;
		a[j+1]=o;
	}
}

快速排序 \(\sf\small\color{CCCCCC}Quick\)

快速排序是基于分治的一种排序算法。 Quick

通过两端指针交换第一个比基准数小的和第一个比基准数大的数,然后把基准数放在所有比他小的与大的之间,从而确定这个数的位置。
再用相同的办法处理左半边和右半边,每次确定一个数,最终完成排序。

void QuickSort(int*a,int size)
{
	if(size<=1)	return;
	int*i=a,*j=a+size-1,base=*a;
	while(i<j)
	{
		while(*j>=base&&i<j)	j--;
		while(*i<=base&&i<j)	i++;
		if(i<j)					Swap(i,j);
	}
	Swap(a,i);
	QuickSort(a,i-a);
	QuickSort(i+1,size-(i-a)-1);
}

归并排序 \(\sf\small\color{CCCCCC}Merge\)

归并排序是一种基于二分递归的稳定排序算法。
每次把活动区域二分,直到分到只有一个 \(\sf\small\color{gray}有序了\) 的时候就开始合并。
每次把左区域和右区域的序列,
用两个指针分别指向序列末尾,
按照小的在前,一个一个放入辅助数组内,
最后在把辅助数组搬回原数组。

void MergeSort(int*a,int size)
{
	if(size<=1)	return;
	int msize=size/2;
	MergeSort(a,msize);
	MergeSort(a+msize,size-msize);
	int*i=a,*j=a+msize,G=0,A[size+2];
	while(G<size)
		if(*i<=*j&&i<a+msize||j>=a+size)
			A[G++]=*i,i++;
		else
			A[G++]=*j,j++;
	for(int k=0;k<size;k++)
		*(a+k)=A[k];
	delete []A;
	return;
}

堆排序 \(\sf\small\color{CCCCCC}Heap\)

就是以数组为基础建堆,然后遍历堆,保证父节点比子节点 大/小 就好。

void preheapsort(int*a,int s,int e)
{
	int f=s,c=s*2+1;
	while(c<=e)
	{
		if(c+1<=e&&a[c]<a[c+1])	c++;
		if(a[f]>=a[c])	return;
		Swap(a[f],a[c]);
		f=c,c=c*2+1;
	}
}
void HeapSort(int*a,int size)
{
	for(int i=(size-2)/2;i>=0;i--)
		preheapsort(a,i,size-1);
	for(int i=size-1;i>0;i--)
		Swap(a[0],a[i]),
		preheapsort(a,0,i-1);
}

所有排序比较

视情况考虑用哪种排序。

算法名称 桶排序 选择排序 冒泡排序 插入排序 快速排序 归并排序 堆排序
英文名 Bucket Selection Bubble Insertion Quick Merge Heap
稳定性 稳定 不稳定 稳定 稳定 不稳定 稳定 不稳定
最优时间复杂度 \(\sf O(n)\) \(\sf O(n^2)\) \(\sf O(n)\) \(\sf O(n)\) \(\sf O(nlogn)\) \(\sf Θ(nlogn)\) \(\sf O(nlogn)\)
平均时间复杂度 \(\sf O(n)\) \(\sf O(n^2)\) \(\sf O(n^2)\) \(\sf O(n^2)\) \(\sf O(nlogn)\) \(\sf Θ(nlogn)\) \(\sf O(nlogn)\)
最劣时间复杂度 \(\sf O(n)\) \(\sf O(n^2)\) \(\sf O(n^2)\) \(\sf O(n^2)\) \(\sf O(n^2)\) \(\sf Θ(nlogn)\) \(\sf O(nlogn)\)
空间复杂度 \(\sf O(w)\) 原地 原地 原地 原地 \(\sf Θ(n)\) 原地

求个逆序对…… \(\sf\small\color{CCCCCC}Invertion\)

在归并的时候就可以顺便求一下。

void preinvertions(int *a,int size,int&ans)
{
	if(size<=1)	return;
	int msize=size/2;
	preinvertions(a,msize,ans);
	preinvertions(a+msize,size-msize,ans);
	int*i=a,*j=a+msize,G=0,A[size+2];
	while(G<size)
		if(*i<=*j&&i<a+msize||j>=a+size)
			A[G++]=*i,i++;
		else
			A[G++]=*j,j++,ans+=msize-(i-a);
	for(int k=0;k<size;k++)
		*(a+k)=A[k];
	delete []A;
	return;
}
int Invertions(int *a,int size)
{
	int A[size+2]={0},ans=0;
	for(int i=0;i<size;i++)
		A[i]=a[i];
	preinvertions(A,size,ans);
	delete []A;
	return ans;
}

完结散花 ^O^

posted @ 2022-10-12 13:10  PCwqyy  阅读(21)  评论(0)    收藏  举报  来源