十大排序算法总结

1.排序算法基础知识

1.1排序算法分类

十种常见排序算法可以分为两大类:

比较类排序:通过比较来决定元素间的相对次序,由于其时间复杂度不能突破O(nlogn),因此也称为非线性时间比较类排序。
非比较类排序:不通过比较来决定元素间的相对次序,它可以突破基于比较排序的时间下界,以线性时间运行,因此也称为线性时间非比较类排序。

1.2 算法复杂度


1.3 知识点

稳定:如果a原本在b前面,而a=b,排序之后a仍然在b的前面。
不稳定:如果a原本在b的前面,而a=b,排序之后 a 可能会出现在 b 的后面。
时间复杂度:对排序数据的总的操作次数。反映当n变化时,操作次数呈现什么规律。
空间复杂度:是指算法在计算机内执行时所需存储空间的度量,它也是数据规模n的函数
注:对于排序算法,我们多数情况下只考虑它的时间复杂度,而对于空间复杂度则可以放宽松一些


2.排序算法分析

/*by kzl*/
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<queue>
#include<stack>
#include<vector>
 
using namespace std;
const int maxx = 1e5+500;
const int INF = 0x3f3f3f3f;
typedef long long LL;
 
 
void print(int arr[],int n){
    for(int i=0;i<n;i++){
        cout<<arr[i]<<" ";
    }
    cout<<endl;
}
//冒泡排序,每一轮比较相邻位置,如果逆序则交换。
void BubbleSort(int arr[],int n){
    for(int i=1;i<n;i++){
        for(int j = 0;j<n-i;j++){
            if(arr[j]>arr[j+1])swap(arr[j+1],arr[j]);
        }
    }
}
 
//选择排序,每一轮选择最小值放到数组的最前面
void selectSort(int arr[],int n){
    for(int i=0;i<n;i++){
        for(int j=i+1;j<n;j++){
            if(arr[i]>arr[j])swap(arr[i],arr[j]);
        }
    }
}
 
//插入排序,保证当前元素之前的元素有序,然后看当前元素能够插入到前面的哪个位置。
void insertSort(int arr[],int n){
    for(int i=1;i<n;i++){
        int temp = arr[i];
        int j = i-1;
        while(temp<arr[j]&&j>=0)j--;
        for(int k = i-1;k>j;k--)arr[k+1] = arr[k];
        arr[j+1] = temp;
    }
}
//快速排序,选一个基值,然后从后面遍历,比他小的放前面,从前面遍历,比他大放后面,不断挖坑填坑。
int partitionsort(int arr[],int le,int ri)
{
    int l = le,r = ri;
    int temp = arr[l];
    while(l<r){
        while(l<r&&arr[r]>temp)r--;
        if(l<r)arr[l] = arr[r];
        while(l<r&&arr[l]<=temp)l++;
        if(l<r)arr[r] = arr[l];
       // cout<<l<<" "<<r<<endl;
    }
    arr[l] = temp;
    return l;
}
 
void quickSort(int arr[],int le,int ri)
{
    if(le>ri)return ;
    int mid = partitionsort(arr,le,ri);
    quickSort(arr,le,mid-1);
    quickSort(arr,mid+1,ri);
}
 
//堆排序,先构建一个最大堆,然后依次交换最大值和数组最末位置的值,保证数组有序。
void heapAdjust(int arr[],int sta,int en)
{
    int temp = arr[sta];
    for(int i=2*sta+1;i<=en;i++)
    {
        if(arr[i]<arr[i+1]&&i<en)i++;
        if(temp>=arr[i])break;
        arr[sta] = arr[i];
        sta = i;
    }
    arr[sta] = temp;
}
 
void heapSort(int arr[],int n)
{
    for(int i = (n)/2;i>=0;i--){
        heapAdjust(arr,i,n-1);
    }
    for(int i=n-1;i>=0;i--){
        swap(arr[i],arr[0]);
        heapAdjust(arr,0,i-1);
    }
}
 
//希尔排序,其实就是插入排序,不过是间隔为D的序列中进行的
void shellInsert(int arr[],int d,int n){
    for(int i=d;i<n;i++){
        int j = j-d;
        int temp = arr[i];
        while(j>=0&&arr[j]>temp)
        {
            arr[j+d] = arr[j];
            j -= d;
        }
        arr[j+d] = temp;
    }
}
 
 
void ShellSort(int arr[],int n)
{
    int d = n/2;
    while(d>=1){
        shellInsert(arr,d,n);
        d/=2;
    }
}
 
//归并排序,先不断的分割区间,至区间只有两个元素,然后在不断地合并子区间
void Mymerge(int arr[],int le,int ri,int ll,int rr){
    int temp[1000];int k = 0;
    int sta = le,en = rr;
    while(le<=ri&&ll<=rr){
        if(arr[le]<arr[ll])temp[k++] = arr[le++];
        else temp[k++] = arr[ll++];
    }
    while(le<=ri)temp[k++] = arr[le++];
    while(ll<=rr)temp[k++] = arr[ll++];
    for(int i = sta;i<=en;i++){
        arr[i] = temp[i-sta];
    }
}
 
 
void mergeSort(int arr[],int le,int ri){
    if(le>=ri)return ;
    int mid = (le+ri)>>1;
    mergeSort(arr,le,mid);
    mergeSort(arr,mid+1,ri);
    Mymerge(arr,le,mid,mid+1,ri);
}
 
//基数排序,对一列数字,先根据个位进行排序,然后根据十位进行排序。。依次
int getbit(int x){
    int bit = 0;
    while(x>0)
    {
        x/=10;
        bit++;
    }
    return bit;
}
//获取数组中最大的数的位数
int maxbit(int arr[],int n)
{
    int ma = -1;
   for(int i=0;i<n;i++){
        ma = max(ma,getbit(arr[i]));
   }
   return  ma;
}
 
void radixSort(int arr[],int n)
{
    int bit = maxbit(arr,n);
    int coun[10],tmp[1000];
    int radio = 1;
    for(int i=0;i<bit;i++){
        memset(coun,0,sizeof(coun));
        for(int j=0;j<n;j++){
            int k = (arr[j]/radio)%10;
            coun[k]++;
        }
        for(int j = 1;j<10;j++){
            coun[j] = coun[j] + coun[j-1];
        }
        for(int j=n-1;j>=0;j--){
             int k = (arr[j]/radio)%10;
             tmp[coun[k]-1] = arr[j];
             coun[k]--;
        }
        for(int j=0;j<n;j++){
            arr[j] = tmp[j];
        }
        radio= radio * 10;
    }
}
//计数排序,将数字映射成数组下标,然后遍历一遍就可知道其所在位置。
void CountSort(int arr[],int n)
{
    int temp[1000];//能进行1000以内数字的排序,取决于数字范围,如有需要,可增大。
    memset(temp,0,sizeof(temp));
    int ma = -1;
    for(int i=0;i<n;i++){
        temp[arr[i]]++;
        ma = max(ma,arr[i]);
    }
    int k = 0;
    for(int i=0;i<=ma;i++){
        for(int j=0;j<temp[i];j++){
            arr[k++] = i;
        }
    }
}
 
//桶排序,计数排序的升级版,实际上计数排序就是桶的个数十分多的时候的例子
 
int f(int x){
//映射函数,决定这个数应该放到哪一个桶里面,此处是简单的除以100,根据我的数据可知,此处有四个桶,0,1,3,4,
//然后对每个桶单独排序,保证下一个桶的最大值必定大于上一个桶的最小值
    return x/100;
}
 
 
 
void bucketSort(int arr[],int n)
{
    int bucketNums = 10;//桶的个数
    vector<int>ve[10];//记录每一个桶里面有的数
    for(int i=0;i<n;i++){
        int aa = f(arr[i]);
        ve[aa].push_back(arr[i]);
    }
    //单独对每个桶排序
    for(int i=0;i<bucketNums;i++){
        if(ve[i].size()==0)continue;
        sort(ve[i].begin(),ve[i].end());
    }
    int k = 0;
    for(int i=0;i<bucketNums;i++){
        int sz = ve[i].size();
        for(int j = 0;j<sz;j++){
            arr[k++] = ve[i][j];
        }
    }
}
 
 
int main(){
int arr[10] = {3,24,76,345,12,87,100,30,21,456};//试验数组
bucketSort(arr,10);
print(arr,10);
return 0;

转载于:https://blog.csdn.net/lwgkzl/article/details/79941786
https://blog.csdn.net/weixin_43442778/article/details/107547310

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值