算法——排序

1、标准函数库sort

头文件:<algorithm>

定义一个数组a,长度为n,则用法为:sort(a,a+n);即可完成数据从小到大排序

也可通过添加谓词进行按照要求进行排序

bool cmp(int a,int b)
{
    return a>b;
}
//调用
sort(a,a+n,cmp);//实现降序排序

2、时间复杂度分析



3、冒泡排序

冒泡排序算法的运作如下:
  1. 比较相邻的元素。如果第一个比第二个大,就交换。
  2. 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。
  3. 针对所有的元素重复以上的步骤,除了最后一个。
  4. 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较
算法时间复杂度为O(n^2)

void maopaopaixu(int a[],int n)
{
    for(int i=0;i<n-1;i++)
    {
        for(int j=0;j<n-i-1;j++)
        {
            if(a[j]>a[j+1])
                swap(a[j],a[j+1]);
        }
    }
}

4、插入排序

插入排序是一种简单的插入排序法,其基本思想是:把待排序的纪录按其关键码值的大小逐个插入到一个已经排好序的有序序列中,直到所有的纪录插入完为止,得到一个新的有序序列。

算法时间复杂度为O(n^2)

void charupaixu(int a[],int n)
{
    for(int i=1;i<n;i++)
    {
        if(a[i-1]>a[i])
        {
            int temp=a[i];
            int j=i;
            while(j>0&&a[j-1]>temp)
            {
                a[j]=a[j-1];
                j--;
            }
            a[j]=temp;
        }
    }
}

5、简单选择排序

它的工作原理是每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完。

选择排序是不稳定的排序

时间复杂度为O(n^2)

void xuanzepaixu(int a[],int n)
{
    for(int i=0;i<n;i++)
    {
        int min=a[i];
        int temp;
        int index=i;
        for(int j=i+1;j<n;j++)
        {
            if(a[j]<min)
            {
                min=a[j];
                index=j;
            }
        }
        temp=a[i];
        a[i]=min;
        a[index]=temp;
    }
}

选择排序(优化):

每一趟查找未排序中的最大值和最小值

#include<iostream>
using namespace std;
void xuanzepaixu(int a[],int n)
{
    for(int i=0;i<n/2+1;i++)
    {
        int maxn=a[i];
        int maxj=i;
        int minn=a[i];
        int minj=i;
        for(int j=i+1;j<=n-i-1;j++)
        {
            if(a[j]>maxn)
            {
                maxn=a[j];
                maxj=j;
            }
            else if(a[j]<minn)
            {
                minn=a[j];
                minj=j;
            }
        }
        int temp=a[i];
        int temp1=a[n-i-1];
        a[i]=minn;
        a[minj]=temp;

        a[n-i-1]=maxn;
        a[maxj]=temp1;
        for(int i=0;i<n;i++)
        {
        cout<<a[i]<<" ";
        }
        cout<<endl;
    }
}
int main()
{
    int n;
    cin>>n;
    int a[n];
    for(int i=0;i<n;i++)
    {
        cin>>a[i];
    }
    xuanzepaixu(a,n);
    for(int i=0;i<n;i++)
    {
        cout<<a[i]<<" ";
    }
}


6、快速排序

通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。

时间复杂度O(nlogn)

void quick(int a[],int m,int n)
{
    if(m<n)
    {
        int k=(m+n)>>1;
        swap(a[m],a[k]);
        int key=a[m];
        int i=m+1;
        int j=n;
        while(i<=j)
        {
            while(i<=n&&a[i]<=key)i++;
            while(j>=m&&a[j]>=key)j--;
            if(i<j)
                swap(a[i],a[j]);
        }
        swap(a[m],a[j]);
        quick(a,m,j-1);
        quick(a,j+1,n);
    }
}

7、归并排序

该算法是采用分治法

将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并

适合于小规模的排序,大规模的较优的排序应选择快排

时间复杂度O(nlogn)

void merge(int a[],int low,int mid,int high)
{
    int n=mid-low+1;
    int m=high-mid;
    int left[n];
    int right[m];
    for(int i=0;i<n;i++)
    {
        left[i]=a[low+i];
    }
    for(int i=0;i<m;i++)
    {
        right[i]=a[mid+i+1];
    }
    int i=0,j=0,k=low;
    while(i<n&&j<m)
    {
        if(left[i]<right[j])
        {
            a[k+1]=left[i++];
        }
        else a[k++]=right[j++];
    }
    while(i<n)
    {
        a[k++]=left[i++];
    }
    while(j<m)
    {
        a[k++]=right[j++];
    }
}
void mergesort(int a[],int low,int high)
{
    if(low<high)
    {
        int mid=(low+high)>>1;
        mergesort(a,low,mid);
        mergesort(a,mid+1,high);
        merge(a,low,mid,high);
    }
}

8.堆排序

堆实际上是一棵完全二叉树,其任何一非叶节点满足性质:key[i]<=key[2i+1]&&key[i]<=key[2i+2]或者key[i]>=key[2i+1]&&key>=key[2i+2],堆排序则是使用大顶堆或小顶堆的性质不断调整,使其满足堆的性质。

#include<iostream>
using namespace std;
void HeapAdjust(int *a,int i,int size)  //调整堆
{
    int lchild=2*i;       //i的左孩子节点序号
    int rchild=2*i+1;     //i的右孩子节点序号
    int max=i;          //临时变量
    if(i<=size/2)        //如果i不是叶节点就不用进行调整
    {
        if(lchild<=size&&a[lchild]>a[max])
        {
            max=lchild;
        }
        if(rchild<=size&&a[rchild]>a[max])
        {
            max=rchild;
        }
        if(max!=i)
        {
            swap(a[i],a[max]);
            HeapAdjust(a,max,size);    //避免调整之后以max为父节点的子树不是堆
        }
    }
}
void BuildHeap(int *a,int size)    //建立堆
{
    int i;
    for(i=size/2; i>=1; i--)  //非叶节点最大序号值为size/2
    {
        HeapAdjust(a,i,size);
    }
}
void HeapSort(int *a,int size)    //堆排序
{
    int i;
    BuildHeap(a,size);
    for(i=size; i>=1; i--)
    {
        swap(a[1],a[i]); //交换堆顶和最后一个元素,即每次将剩余元素中的最大者放到最后面
        HeapAdjust(a,1,i-1);      //重新调整堆顶节点成为大顶堆
    }
}
int main()
{
    int n;
    cin>>n;
    int a[n];
    for(int i=1; i<=n; i++)
    {
        cin>>a[i];
    }
    HeapSort(a,n);
    for(int i=1; i<=n; i++)
    {
        cout<<a[i]<<" ";
    }
}

9、计数排序

该算法的时间复杂度可以做到O(n),空间复杂度比较大
#include<iostream>
#include<string.h>
using namespace std;
int c[1000];
int ranked[1000];
int main()
{
    memset(c,0,sizeof(c));
    int n;
    cin>>n;
    int a[n];
    int k=0;
    for(int i=0;i<n;i++)
    {
        cin>>a[i];
        if(a[i]>k)
            k=a[i];//a[i]中最大值
        c[a[i]]++;
    }
    for(int i=1;i<=k;i++)
    {
        c[i]+=c[i-1];
    }
    for(int i=n-1;i>=0;i--)
    {
        ranked[--c[a[i]]]=a[i];
    }
    for(int i=0;i<n;i++)
    {
        cout<<ranked[i]<<" ";
    }
}

10、希尔排序

插入排序中的一种,也称缩小增量排序
时间复杂度与每次所选择的增量数有关
#include<iostream>
using namespace std;
int xier(int a[],int n)
{
    int d=n>>1;
    while(d>=1)
    {
        for(int i=d;i<n;i++)
        {
            if(a[i]<a[i-d])
            {
                int j=i-d;
                int x=a[i];
                a[i]=a[i-d];
                while(x<a[j]&&j>=0)
                {
                    a[j+d]=a[j];
                    j-=d;
                }
                a[j+d]=x;
            }
        }
        d=d>>1;
    }
}
int main()
{
    int n;
    cin>>n;
    int a[n];
    for(int i=0;i<n;i++)
    {
        cin>>a[i];
    }
    xier(a,n);
    for(int i=0;i<n;i++)
        cout<<a[i];
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值