排序(上)
都以从小到大为例
1.冒泡排序:
顾名思义每次比较两个小的那个冒上来,大的那个沉下去。
for(i=0;i<n-1;i++)
{
for(j=0;j<n-1-i;j++)
{
if(a[j]>a[j+1]
{
t=a[j];
a[j]=a[j+1];
a[j+1]=t;
}
}
}
2.插入排序:
先取出未排序序列中的第一个元素,依次与已排序序列中元素比较并右移,直到放进合适的位置。
for(i=0;i<n;i++)
{
t=a[i];
for(j=n-1;j>=0&&a[j-1]>t;j--)
{
a[j]=a[j-1];
}
a[j]=t;
}
3.希尔排序:
这种方法实质上是一种分组插入方法。先取一个小于n的m1作为第一个增量,把数组m1个组。所有距离为m1的倍数的记录放在同一个组中。先在各组内进行直接插入排序;然后,取第二个增量m2<m1重复上述的分组和排序,直至所取的增量m=1(m<m-1<…<m2<m1),即所有记录放在同一组中进行直接插入排序为止 。
for(m=n/2;n>0;m/=2)
{
for(i=0;i<m;i++)
{
for(j=i+m;j<n;j+=m)
{
if(a[j]<a[j-m]
{
int t=a[j];
int k=j-m;
while(k>0&&a[k]>t)
{
a[k+m]=a[k];
k-=m;
}
a[k+m]=t;
}
}
}
}
4.堆排序:
利用最大堆(或者最小堆)输出堆顶元素,即最大值(或最小值),将剩余元素重新生成最大堆(或者最小堆),继续输出堆顶元素,重复此过程,直到全部元素都已输出,得到的输出元素序列即为有序序列。
//a[]看成一颗完全二叉树
//root当前的父节点位置
//size总节点树
void heapsort(int a[],int root,int size)
{
if(root<size)//左子树和右字数的位置
{
int l=2*root+1;
int r=2*root+2;
int max=root;//把当前父节点位置看成是最大的
if(l<size) //如果比当前根元素要大,记录它的位置
{
if(a[max]<a[l])
max=l;
}
if(r<size) //如果比当前根元素要大,记录它的位置
{
if(a[max]<a[r])
max=r;
}
if(max!=root)//如果最大的不是根元素位置,那么就交换
{
int t=a[max];
a[max]=a[root];
a[root]=t;
heapsort(a[],max,size);//继续比较,直到完成一次建堆
}
}
}
5.归并排序:
采用的叫分治的思想,将数组划分为两个子数组,然后递归将每个子数组再进行划分,直到数组中只剩一下一个元素,然后开始排序合并,直到将所有的子数组合并完成,整个数据就是有序的啦。时间复杂度:NlogN。
思路:先将无序序列利用二分法划分为两个子序列,直至每个子序列只有一个元素,一个元素序列必然有序,然后再对有序子序列两两进行合并排序。合并方法是循环的将两个有序子序列当前的首元素进行比较,较小的元素取出,放入合并序列的左边空置位,直至其中一个子序列的最后一个元素放入合并序列中。最后将另一个子序列的剩余元素按顺序逐个放入合并序列尾部。
long long int c[10000],a[10000];
void paixu(long long int a[100000],long long int l,long long int mid,long long int r)
{
long long int i=l,j=mid+1,k=0;
while(i<=mid&&j<=r)
{
if(a[i]<=a[j])
c[k++]=a[i++];
else
{
c[k++]=a[j++];
}
}
while(i<=mid)
c[k++]=a[i++];
while(j<=r)
c[k++]=a[j++];
for(i=l;i<=r;i++)
{
a[i]=c[i-l];
}
}
void merge(long long int a[100000],long long int l,long long int r)
{
long long int mid;
if(l==r)
return;
mid=(l+r)/2;
merge(a,l,mid);
merge(a,mid+1,r);
paixu(a,l,mid,r);
}
4.例题:
求逆序数。
样例
样例输入 Copy
2
2
1 1
3
1 3 2
样例输出 Copy
0
1
在归并的基础上加上sum即可
代码:
#include<stdio.h>
long long int sum=0;
long long int c[10000],a[10000];
void paixu(long long int a[],long long int l,long long int mid,long long int r)
{
int i=l,j=mid+1,k=l;
while(i<=mid&&j<=r)
{
if(a[i]<=a[j])
c[k++]=a[i++];
else
{
c[k++]=a[j++];
sum+=mid-i+1;
}
}
while(i<=mid)
c[k++]=a[i++];
while(j<=r)
c[k++]=a[j++];
for(i=l;i<=r;i++)
{
a[i]=c[i];
}
}
void merge(long long int a[],long long int l,long long int r)
{
long long int mid;
if(l<r)
{
mid=(l+r)/2;
merge(a,l,mid);
merge(a,mid+1,r);
paixu(a,l,mid,r);
}
}
int main()
{
long long int n,i,t;
scanf("%lld",&t);
while(t--)
{
sum=0;
scanf("%lld",&n);
for(i=0;i<n;i++)
{
scanf("%lld",&a[i]);
}
merge(a,0,n-1);
printf("%lld\n",sum);
}
return 0;
}