<学习笔记>排序模板

全面解析各类排序算法
本文整理了包括选择排序、冒泡排序、桶排序、插入排序、快速排序、归并排序和堆排序在内的多种排序算法,详细阐述了它们的基本思想、优缺点,并对STL中的排序进行了讨论。同时,对比了不同排序算法的稳定性与时间复杂度,为理解和应用排序算法提供了全面的参考。

*PS:整理自小蓝课件qwq

选择排序

基本思想:每一趟从待排序的数据元素中选出最小(或最大)的一个元素,顺序放在待排序的数列的最前,直到全部待排序的数据元素排完

优:稳定
缺:慢

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;

int n;
int a[100010];

void SelectSort()
{
    for(int i=1;i<n;++i)
    {
        int k=i;
        for(int j=i+1;j<=n;++j)
           if(a[j]<a[k]) k=j;
        if(k!=i) swap(a[i],a[k]);
    }
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;++i)
      scanf("%d",&a[i]);
    SelectSort();
    for(int i=1;i<=n;++i)
      printf("%d ",a[i]);
    return 0;
}

冒泡排序

从1到n依次比较相邻的两个数,把大的放前面,小的放后面。第一遍排序结束时,最小的一定排到最后。重复上述过程,仍从第1个数开始交换,直到交换到倒数第2个数……
由于在排序过程中总是大数往前,小数往后,相当气泡上升,所以叫冒泡排序。
优化:设置一个bool变量判断当前有无排好序。

优:稳定
缺:慢

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;

int n;
int a[100010];

void Sort()
{
     int l=n;
     bool change;
     do
     {
         change=false;
         for(int i=1;i<l;++i)
           if(a[i]<a[i+1]) 
           {
               swap(a[i],a[i+1]);
               change=true;
           }
         --l;    
     }while(change);
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;++i)
      scanf("%d",&a[i]);
    Sort();
    for(int i=1;i<=n;++i)
      printf("%d ",a[i]);
    return 0;
}

桶排序

思想:若待排序的记录的关键字在一个明显有限范围内(整型)时,可设计有限个有序桶,每个桶装入一个值(当然也可以装入若干个值),顺序输出各桶的值,将得到有序的序列。

优:思想简单,代码容易实现
缺:排序的数字小。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;

int n,k;
int a[1010];

int main()
{
     scanf("%d",&n);
     for(int i=1;i<=n;i++)  
     {
         scanf("%d",&k);   
         ++a[k];                
     }
     for(int i=0; i<=1000;i++) 
     while(a[i]>0)  
     {  
         printf("%d ",a[i]);
         --a[i];
     }    
     return 0;
}

插入排序

思想:维护有序区1~i,每次插入第i+1个元素并维护有序性,直到1~n变为一个有序区。其算法的时间复杂性为O(n2)插入排序适用于原先数据已经排列好,插入一个新数据的情况。

优:
缺:慢。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;

int n;
int a[100010];

void InsertSort()
{
    for(int i=2;i<=n;++i)
    {
        int k=a[i],j=i-1;
        while(k<a[j])
        {
            a[j+1]=a[j];
            --j;
        }
        a[j+1]=k;
    }
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;++i)
      scanf("%d",&a[i]);
    InsertSort();
    for(int i=1;i<=n;++i)
      printf("%d ",a[i]);
    return 0;
}

快速排序

快速排序是对冒泡排序的一种改进。它的基本思想是:通过一趟排序将待排记录分割成独立的两部分,其中一部分记录的关键字均比另一部分记录的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序。O(nlog2n)。

优:速度快
缺:不稳定

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;

int n;
int a[100010];

void qsort(int L,int R)
{
    int l=L,r=R;
    int k=a[(l+r)>>1];
    while(l<=r) 
    {
        while(a[l]<k) ++l;
        while(a[r]>k) --r;
        if(l<=r) swap(a[l],a[r]),++l,--r;
    }
    if(l<R) qsort(l,R);
    if(L<r) qsort(L,r);
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;++i)
      scanf("%d",&a[i]);
    qsort(1,n);
    for(int i=1;i<=n;++i)
      printf("%d ",a[i]);
    return 0;
}

归并排序

将两个或两个以上有序的数列(或有序表),合并成一个仍然有序的数列(有序表),这种操作称为归并操作。这样的方法经常用于多个有序的数据文件归并成一个有序的数据文件。若将两个有序表合并成一个有序表则称为二路归并,同理,有三路归并、四路归并等。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;

int n;
int a[100010],b[100010];

void Done(int l,int mid,int r)
{
    int i=l,j=mid+1,k=l-1;
    while(i<=mid&&j<=r)
    {
        if(a[i]<a[j]) b[++k]=a[i],++i;
        else b[++k]=a[j],++j;
    }
    while(i<=mid) b[++k]=a[i],++i;
    while(j<=r)   b[++k]=a[j],++j;
    for(i=l;i<=r;++i)
      a[i]=b[i];
}
void MergeSort(int l,int r)
{
    if(l==r) return ;
    int mid=(l+r)>>1;
    MergeSort(l,mid);
    MergeSort(mid+1,r);
    Done(l,mid,r); 
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;++i)
      scanf("%d",&a[i]);
    MergeSort(1,n);
    for(int i=1;i<=n;++i)
      printf("%d ",a[i]);
    return 0;
}

堆排序

不断弹出堆顶元素。
(偷懒直接粘上堆的模板)

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;

int N;
int a[100010];

void creat(int n)
{
    int k,f=1;
    while((n<<1)<=N&&f)
    {
        k=n;
        if((n<<1)<=N&&a[n<<1]<a[k]) k=n<<1;
        if((n<<1|1)<=N&&a[n<<1|1]<a[k]) k=n<<1|1;
        if(k!=n) swap(a[n],a[k]),n=k;
        else f=0; 
    }
}
void make()
{
    for(int i=N/2;i>=1;--i)
       creat(i); 
}
int ask_top()
{
    return a[1];
}
void pop()
{
    swap(a[1],a[N]),--N;
    creat(1);
}
bool empty()
{
    if(!N) return true;
    return false;
}
void Sort()
{
    int l=N;
    while(N) pop();
    for(int i=l;i>=1;--i)
      printf("%d ",a[i]);
}
int size()
{
    return N;
}
void push(int k)
{
    ++N;
    int n=N,f=1;
    a[n]=k;
    if(n==1) return; 
    while(n>1&&f)
    {
        if(a[n]<a[n>>1]) swap(a[n],a[n>>1]);
        else f=0;
        n>>=1; 
    }
    return;
}
int main()
{
   scanf("%d",&N);
   for(int i=1;i<=N;++i)
     scanf("%d",&a[i]);
   make();
   Sort();
   return 0;    
} 

STL

函数名功能描述
sort对给定区间所有元素进行排序
stable_sort对给定区间所有元素进行稳定排序
partial_sort对给定区间所有元素部分排序
partial_sort_copy对给定区间复制并排序
nth_element找出给定区间的某个位置对应的元素
is_sorted判断一个区间是否已经排好序
partition使得符合某个条件的元素放在前面
stable_partition相对稳定的使得符合某个条件的元素放在前面

各种排序算法的比较

  • 稳定性比较
    (排序的稳定性是指如果在排序的序列中,存在前后相同的两个元素的话,排序前和排序后他们的相对位置不发生变化)
    插入排序、冒泡排序、二叉树排序、归并排序及其他线形排序是稳定的。
    选择排序、希尔排序、快速排序、堆排序是不稳定的。
  • 时间复杂度比较
    插入排序、冒泡排序、选择排序的时间复杂性为O(n2);快速排序、堆排序、归并排序的时间复杂性为O(nlog2n);桶排序的时间复杂性为O(n);
    *在最好情况下,直接插入排序和冒泡排序最快;在平均情况下,快速排序最快;在最坏情况下,堆排序和归并排序最快。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值