几种排序算法的总结

类型时间复杂度(平均)时间复杂度(最坏)时间复杂度(最好)空间复杂度稳定性
插入排序 On2 On2 On O1 稳定
归并排序 Onlogn Onlogn Onlogn On 稳定
快速排序 Onlogn On2 On O(nlogn)不稳定
堆排序 Onlogn nlogn nlogn O1 不稳定
选择排序 On2 n2 n2 O1 不稳定
冒泡排序 On2 n2 n2 O1 稳定
计数排序 On+k On+k

1.插入排序
可以联想成打扑克时手里拿牌的一个过程,手里的牌总是有序的,摸的牌依次比较,放入正确的位置。

#include<iostream>
#include<vector>
using namespace std;
void insertsort(vector<int> &arr)
{
    for(int i=1;i<arr.size();i++)//i与之前的进行比较
    {
        int j=i-1;
        int temp=arr[i];
        while(j>=0 && arr[j]>arr[i] )
        {
            arr[j+1]=arr[j];        
            j--;
        }
        arr[j+1]=temp;  
    }

}
int main()
{
    vector<int> arr;
    arr.push_back(2);
    arr.push_back(1);
    arr.push_back(4);
    arr.push_back(3);
    arr.push_back(7);
    arr.push_back(6);

    insertsort(arr);
    for(int i=0;i<arr.size();i++)
    {
        cout<<arr[i]<<endl;
    }

}

2.归并排序
联想成桌面有两组牌,依旧比较牌面最上面的牌最小的排好序。

void merge(vector<int> &arr,int p,int q,int r)
{

    vector<int> L;
    vector<int> R;

    for(int i=p;i<=q;i++)
    {
        L.push_back(arr[i]);
    };
    L.push_back(INT_MAX);
    for(int i=q+1;i<=r;i++)
    {
        R.push_back(arr[i]);
    }
    int i=0,j=0;
    R.push_back(INT_MAX);
    for(int k=p;k<=r;k++)
    {
        if(L[i]<=R[j])
        {
            arr[k]=L[i];
            i++;
        }
        else if(R[j]<=L[i])
        {
            arr[k]=R[j];
            j++;
        }
    }
}
void mergesort(vector<int> &arr,int p, int r)
{
    if (p<r)  
    {  
        int q = (p+r)/2;  
        mergesort(arr, p, q);  
        mergesort(arr, q+1, r);  
        merge(arr, p, q, r);  
    }  
}

3.快速排序
快排主要在于一趟快排的过,即从后向前依次寻找比x小的数,找到了交换,同时i增加。使得x的左边小于x,右边大于x。

int partition(vector<int> &A,int p,int r)
{
    int i=p-1;
    int x=A[r];
    for(int j=p;j<r;j++)
    {
        if(A[j]<x)
        {
            i++;
            swap(A[i],A[j]);
        }
    }
    swap(A[i+1],A[r]);
    return i+1;
}

void quicksort(vector<int> &A,int p,int r)
{
    if(p<r)
    {
        int q=partition(A,p,r);
        quicksort(A,p,q-1);
        quicksort(A,q+1,r);
    }
}

4.堆排序
建立最大堆,联想建立堆首先要想到维护堆的过程,维护堆则需要比较节点i的左右孩子是否大于i,如果大于则交换,同时继续向下维护。
建立堆则是除去叶子节点,对其他节点依次进行维护。
现在堆顶元素是最大的元素,交换堆顶与arr[n],堆的大小减1,则去掉堆顶,最剩余元素进行维护。

void heapify(vector<int> &arr,int heap_size,int i)
{

    int left=2*i+1;
    int right=2*i+2;
    int largest;
    if(left<heap_size &&arr[left]>arr[i])
         largest=left;
    else
        largest=i;
    if(right<heap_size &&arr[right]>arr[largest])
        largest=right;
    if(largest!=i)
    {
        swap(arr[i],arr[largest]);
        heapify(arr,heap_size,largest);
    }
}

void build_heap(vector<int> &arr)
{
    //除去叶子节点,进行维护
    for(int i=(arr.size()-1)/2;i>=0;i--)
        heapify(arr,arr.size(),i);
}

void heap_sort(vector<int> &arr)
{
    //先建堆
    build_heap(arr);
    int heap_size=arr.size();
    //再维护,A[0]现在是最大的元素,与A[i]交换,再维护
    for(int i=arr.size()-1;i>0;i--)
    {
        swap(arr[0],arr[i]);
        heap_size=heap_size-1;
        heapify(arr,heap_size,0);
    }
}

5.选择排序
这个比较简单,其实就是依次比较出最小的数。

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

6.冒泡排序
联想鱼吐泡泡的样子,大的泡泡总是在上面,所以需要将相邻的两个数进行比较,将后面的较大数先比较出来

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

7.计数排序
联想哈希表,计数排序从名字上记忆就是比x小的有m个,则x应该在m位(数组从0开始)

vector<int> CountingSort(vector<int> arr,int k)//k是arr数组元素的范围,0-k
{
    int len=arr.size();

    vector<int> temp(k+1,0);
    vector<int> res(len,0);

    for(int i=0;i<len;i++)
    {
        temp[arr[i]]=temp[arr[i]]+1;
    }

    for(int i=1;i<=k;i++)
    {
        temp[i]=temp[i-1]+temp[i];
    }

    for(int i=len-1;i>=0;i--)
    {
        res[temp[arr[i]]-1]=arr[i];
        temp[arr[i]]=temp[arr[i]]-1;
    }
    return res;
}

8.基数排序

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值