排序专题(桶排序,冒泡,快排,堆排序)

1.最简单的排序——桶排序(简化版)
优点:快速,简单
缺点:数据足够大时,会造成严重的空间浪费;不能解决小数问题
理解:桶排序就是开一个足够大的数组,数组下标最大值(设为x,a[x])要大于需要排序的数据最大值。设输入为ni,则只要令a[ni]++,就可以确定相同ni的个数,然后从从0到n,只要a[ni]不为0就可以按顺序正确的输出ni。另外由于桶排序的特殊性,桶排序还能够解决元素重复问题。

代码:

#include<stdio.h>
#include<algorithm>
using namespace std;
int a[1010];
int main()
{
    int n,ni,i;
    scanf("%d",&n);
    fill(a,a+n,0);
    for(i=1; i<=n; i++)
    {
        scanf("%d",&ni);
        a[ni]++;
    }
    for(i=1; i<=1000; i++)//浪费空间
        if(a[i])
            while(a[i]--)//不输出重复元素的话就不需要这一行
                printf("%d ",i);
    return 0;
}

2.冒泡排序
优点: 能解决小数问题,稳定
缺点: 时间复杂度O(N2);
理解: 冒泡排序的核心就是双重嵌套for循环,每次比较相邻的两个元素,如果他们的顺序错误,就交换。冒泡冒泡,每一趟只能确定将一个数交换。由于冒泡排序每次只比较相邻两个元素。

#include<stdio.h>
#include<algorithm>
using namespace std;
int a[20];
int main()
{
    int n,j,i,t;
    scanf("%d",&n);
    fill(a,a+n,0);
    for(i=0; i<n; i++)
        scanf("%d",&a[i]);
    for(i=0; i<n-1; i++)
        for(j=0; j<n-1-i; j++)
            if(a[j]>a[j+1])
            {//注意别把i,t搞混了
                t=a[j];a[j]=a[j+1];a[j+1]=t;
            }
    for(i=0;i<n;i++)
        printf("%d ",a[i]);
    return 0;
}

3.快速排序
优点: 极快
缺点: 不稳定
理解: 每次排序的时候设置一个基准点,将小于等于基准点的数放左边,反之放右边。这样交换的时候就不会想冒泡排序那样每次只搞定相邻的了。快排的每次排序是跳跃式的,运用了二分思想。

#include<stdio.h>
#include<algorithm>
using namespace std;
int a[1020],n;
struct node
{
  int tim;
  int cre;
}b[100];
void insertsort(node A[],int n)  //结构体从大到小快排
{
	for(int p=1;p<n;p++)
	{
		int tmp=A[p].cre;
		int tmp2=A[p].tim;
		int i=p;
		for(;i>0&&A[i-1].cre<tmp;i--)
		{
			A[i].tim=A[i-1].tim;
			A[i].cre=A[i-1].cre;
		}
		A[i].cre=tmp;
		A[i].tim=tmp2;
	}
}
void quick(int l,int r)
{
    int i,j,t,temp;
    if(l>r) return;
    i=l;j=r;
    temp=a[l];
    while(i!=j)
    {
        while(a[j]>=temp&&i<j) j--;
        while(a[i]<=temp&&i<j) i++;
        if(i<j)
            t=a[i],a[i]=a[j],a[j]=t;
    }
    a[l]=a[i];
    a[i]=temp;
    quick(l,i-1);
    quick(i+1,r);
    return;
}
int main()
{
    int j,i,t;
    scanf("%d",&n);
    fill(a,a+n,0);
    for(i=1; i<=n; i++)
        scanf("%d",&a[i]);
    quicksort(1,n);
    for(i=1; i<=n; i++)
        printf("%d ",a[i]);
    return 0;
}

4.堆排序
优点: 快,时间复杂度O(NlogN)
缺点: 堆排序将需要做两个步骤:建堆,排序(调整堆)。所以一般在小规模的序列中不合适,
理解: 可以建立最大堆,每次将第一个和最后一个元素互换,然后最大元素到了最后一位归位,再接着调整顶部元素再将堆的大小减1。

#include<stdio.h>
#include<algorithm>
using namespace std;
int a[1020],n;
void swap(int i,int j)
{
    int t;
    t=a[i];a[i]=a[j];a[j]=t;
    return;
}
void siftdown(int i) //下沉函数,确保堆的正确性
{
    int t,flag=0;
    while(i*2<=n&&flag==0)
    {
        if(a[i]<a[i*2])
            t=i*2;
        else t=i;
        if(i*2+1<=n) 
        {
            if(a[t]<a[i*2+1])
                t=2*i+1;
        }
        if(t!=i)
        {
            swap(t,i);i=t;
        }
        else flag=1;
    }
    return;
}
void headsort()
{
    while(n>1)
    {
        swap(1,n);
        n--;
        siftdown(1);     //将最后一位换到第一位,然后调整。
    }
    return;
}
int main()
{
    int j,i,t,num;
    scanf("%d",&num);
      n=num;
    for(i=1; i<=num; i++)
        scanf("%d",&a[i]);
    for(i=n/2;i>=1;i--)   //建堆
        siftdown(i);      //调整
    headsort();
    for(i=1; i<=num; i++)
        printf("%d ",a[i]);
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值