经典排序算法总结(C++)

常见的分类算法还可以根据排序方式分为两大类:比较排序和非比较排序,比较排序就是常见的几种。  

非比较排序的特点是时间复杂度很低,都是线性复杂度O(n),但是非比较排序受到的限制比较多,不是通用的排序算法,有如下几种:

       1)计数排序(Count Sort)(复杂度O(n+k)(其中k是待排序的n个数字中最大值)

  2)基数排序(Bucket Sort)(复杂度O(nk)(其中k是最大数字的位数)

       3)桶排序(Radix Sort)(复杂度O(n+k)(其中k是待排序的n个数字中最大值)

目录

一.快速排序。

二.归并排序。

三.冒泡排序。

适用场景:

四.选择排序.

五.插入排序。

适用场景


时间及空间复杂度如下:

 稳定性:两个相等的数在排序之前和排序之后的相对位置不变。

一.快速排序。

算法思想如下:

选取一个基准值,将小于基准值的放在基准值前面,大于基准值的放在基准值后面。

算法模板如下

#include<bits/stdc++.h>
using namespace std;
void quick_sort(int a[],int l,int r)
{
	if(l>=r) return ;
	int i=l-1,j=r+1,x=a[l+r>>1];
	while(i<j)
	{
		do i++;while(a[i]<x);
		do j--;while(a[j]>x);
		if(i<j) swap(a[i],a[j]);
	}
	quick_sort(a,l,j),quick_sort(a,j+1,r);
}

例题:https://www.acwing.com/problem/content/787/

模板应用:

#include<bits/stdc++.h>
using namespace std;

void quick_sort(vector<int>& res,int l,int r){
    if(l>=r) return;
    int mid = res[l+r>>1];
    int i=l-1,j=r+1;
    while(i<j){
        while(res[++i]<mid);
        while(res[--j]>mid);
        if(i<j) swap(res[i],res[j]);
    }
    quick_sort(res,l,j);
    quick_sort(res,j+1,r);
}

int main(){
    int n;
    cin>>n;
    vector<int> res(n);
    for(int i=0;i<n;i++) cin>>res[i];
    quick_sort(res,0,n-1);
    for(int i=0;i<n;i++)
        cout<<res[i]<<" ";
}

二.归并排序。

算法思想:

利用分治思想将一个数组分成两段,将两端较小的放在前面。

 

模板如下:

void merge_sort(int a[],int l,int r)
{
	if(l>=r) return ;
	int mid=l+r>>1;
	merge_sort(a,l,mid);
	merge_sort(a,mid+1,r);
	int k=0,i=l,j=mid+1;
	while(i<=mid&&j<=r)
	{
		if(a[i]<a[j]) tmp[k++]=a[i++];
		else tmp[k++]=a[j++];
	}
	while(i<=mid) tmp[k++]=a[i++];
	while(j<=r) tmp[k++]=a[j++];
	
	for(int i=l,j=0;i<r;i++,j++) q[i]=tmp[i];
	
}

例题:https://www.acwing.com/problem/content/789/

模板应用:

#include <bits/stdc++.h>
using namespace std;

int temp[100010];

void merge_sort(vector<int>& res,int l,int r){
    if(l>=r) return ;
    int mid = l+r>>1;
    int i=l,j=mid+1;
    int k=0;
    merge_sort(res,l,mid);
    merge_sort(res,mid+1,r);
    
    while(i<=mid&&j<=r){
        
        if(res[i]<=res[j]) temp[k++]=res[i++];
        else temp[k++] = res[j++];
    }
    while(i<=mid) temp[k++]=res[i++];
    while(j<=r) temp[k++] = res[j++];
    for(int i=l,j=0;i<=r;i++,j++) res[i]=temp[j];
    
}

int main(){
    int n;
    cin>>n;
    vector<int> res(n);
    for(int i=0;i<n;i++)
        cin>> res[i];
    merge_sort(res,0,n-1);
    for(int i=0;i<n;i++)
        cout<<res[i]<<" ";
}

三.冒泡排序。

算法思想:

比较相邻的元素,如果反序则交换,经过第一趟后就能找出最大的元素,然后重复便可。

模板如下: 

void Bubble_sort(int arr[],int n){
    int temp;
    for(int i=0;i<n-1;i++){
        for(int j=0;j<n-i-1;j++){
            if(arr[j]>arr[j+1]){
                temp = arr[j];
                arr[j] = arr[j+1];
                arr[j+1] = temp;
            }        
   }
}

适用场景:

冒泡排序思路简单,代码也简单,特别适合小数据的排序。但是,由于算法复杂度较高,在数据量大的时候不适合使用。

四.选择排序.

算法思想:

先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾,重复第二步,直到所有元素均排序完毕。

模板如下:

void select_sort(vector<int>&arr){
    int x = arr[0];
    int temp;
    for(int i=0;i<arr.size()-1;i++){
        int min = i;
        for(int j=i+1;j<arr.size();j++){
            if(arr[i]>arr[j]){
                min = j;//比较的次数少
            }
        }
        swap(arr[i],arr[j]);
}
}

虽然数组实现的选择排序不稳定,但链表实现的选择排序是稳定的。

五.插入排序。

算法思想:

先把待排序的数组分成已排序和未排序两部分,初始的时候把第一个元素认为是已排好序的,从第二个元素开始,在已排好序的子数组中寻找到该元素合适的位置并插入该位置,重复上述过程直到最后一个元素被插入有序子数组中。

模板如下:

void insertion_sort(vector<int>&arr){
    for(int i=0;i<arr.size()-1;i++){
        for(int j=i;j>0;j--){
            if(arr[j]<arr[j-1]
                swap(arr[j],arr[j-1]);
        }
    }

}

使用场景

插入排序由于O( n2 )的复杂度,在数组较大的时候不适用。但是,在数据比较少的时候,是一个不错的选择,一般做为快速排序的扩充。例如,在STL的sort算法和stdlib的qsort算法中,都将插入排序作为快速排序的补充,用于少量元素的排序。又如,在JDK 7 java.util.Arrays所用的sort方法的实现中,当待排数组长度小于47时,会使用插入排序。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ranyh524

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值