八大排序算法

1.直接插入排序

void InsertSort(int *arr, int length)
{
    for(int i=1; i<length; ++i)
    {
        if(arr[i]<arr[i-1])
        {
            int tmp=arr[i];
            int j;
            for(j=i; j-1>=0 && tmp<arr[j-1]; --j)//后移
            {
                arr[j]=arr[j-1];
            }
            arr[j]=tmp;//插入
        }
    }
}

 

2.希尔排序

void ShellInsert(int *arr, int length, int dk)
{
    for(int i=dk; i<length; i=i+dk)
    {
        if(arr[i]<arr[i-dk])
        {
            int tmp=arr[i];
            int j;
            for(j=i; j-dk>=0 && tmp<arr[j-dk]; j=j-dk)//后移
            {
                arr[j]=arr[j-dk];
            }
            arr[j]=tmp;//插入
        }
    }
}
void ShellSort(int *arr, int length)
{
    int dlta[]={5, 3, 1};
    for(unsigned long i=0; i<sizeof(dlta)/4; ++i)
    {
        ShellInsert(arr, length, dlta[i]);//做一趟增量为dlta[i]的插入排序
    }
}

 

3.简单选择排序

void SelectSort(int *arr, int length)
{
    for(int i=0; i<length; ++i)
    {
        int min=i;
        for(int j=i+1; j<length; ++j)//选择最小
        {
            if(arr[min]>arr[j])min=j;
        }
        int tmp=arr[i];//交换
        arr[i]=arr[min];
        arr[min]=tmp;
    }
}

 

4.堆排序

void HeapAdjust(int *arr, int s, int m)
{
    int tmp=arr[s];
    for(int j=2*s+1; j<=m; j=2*j+1)//j表示s的子节点,由于数组下标从0开始,故j=2*s+1
    {
        if(j<m && arr[j]<arr[j+1])++j;//如果右子树存在,则j指向左右子树中最大的
        if(tmp>arr[j])break;//如果不需交换就退出,否则就令父节点的值等于子节点,令s=j往下接着比较
        arr[s]=arr[j];
        s=j;
    }
    arr[s]=tmp;//插入
}
void HeapSort(int *arr, int length)
{
    int i;
    int tmp;
    for(i=length/2-1; i>=0; --i)
    {
        HeapAdjust(arr,i,length-1);//调整为大顶堆
    }
    for(i=length-1; i>0; --i)//交换第一个元素
    {
        tmp=arr[0];
        arr[0]=arr[i];
        arr[i]=tmp;
        HeapAdjust(arr,0,i-1);//自上而下,重新调整为大顶堆
    }
}
/******************************************************************************/或者另外一种更加易懂的写法
void HeapAdjust(vector<int> &numbers, int begin, int end) { int parent=begin; int child=parent*2+1; while(child<=end) { if(child+1<=end && numbers[child]<numbers[child+1])++child; if(numbers[parent]<numbers[child]) { int tmp=numbers[parent]; numbers[parent]=numbers[child]; numbers[child]=tmp; } parent=child; child=parent*2+1; } } void HeapSort(vector<int> &numbers, int length) { for(int i=length/2-1; i>=0; --i)HeapAdjust(numbers, i, length-1); for(int i=length-1; i>0; --i) { int tmp=numbers[0]; numbers[0]=numbers[i]; numbers[i]=tmp; HeapAdjust(numbers, 0, i-1); } }

 

5.冒泡排序

void BubbleSort(int *arr, int length)
{
    for(int i=length-1; i>=1; --i)
    {
        for(int j=1; j<=i; ++j)
        {
            if(arr[j-1]>arr[j])//交换
            {
                int tmp=arr[j-1];
                arr[j-1]=arr[j];
                arr[j]=tmp;
            }
        }
    }
}

 

6.快速排序

#include<iostream>
using namespace std;
int Partition(int *arr, int low, int high)
{
    int tmp=arr[low];
    while(low<high)
    {
        while(low<high && arr[high]>=tmp)--high;
        arr[low]=arr[high];
        while(low<high && arr[low]<=tmp)++low;
        arr[high]=arr[low];
    }
    arr[low]=tmp;
    return low;
}
void QuickSort(int *arr, int low, int high)
{
    if(low<high)
    {
        int mid=Partition(arr, low, high);//一分为二
        QuickSort(arr, low, mid-1);//对左边进行一次快排
        QuickSort(arr, mid+1, high);//对右边进行一次快排
    }
}
int main()
{
    int arr[]={49, 38, 65, 97, 76, 13, 27, 49};
    QuickSort(arr, 0, 7);
    return 0;
}

 

7.归并排序

void Merge(int *tmp, int *arr, int start, int mid, int end)
{
    int i, j, k;
    for(i=start, j=mid+1, k=start; i<=mid && j<=end; ++k)
    {
        if(tmp[i]<tmp[j])arr[k]=tmp[i++];
        else arr[k]=tmp[j++];
    }
    while(i<=mid)arr[k++]=tmp[i++];
    while(j<=end)arr[k++]=tmp[j++];
    for(int idx=start; idx<=end; ++idx)tmp[idx]=arr[idx];//将排好序的arr[start...end]复制到tmp[start...end]中
}
void MSort(int *arr, int *tmp, int start, int end)
{
    if(start==end)
    {
        tmp[start]=arr[start];
        return;
    }
    else if(start>end) return;
    else
    {
        int mid=(start+end)/2;//从中间分界
        MSort(arr, tmp, start, mid);//对arr[start...mid]进行一次归并排序,排序结果放至tmp[start...mid]
        MSort(arr, tmp, mid+1, end);//对arr[mid+1...end]进行一次归并排序,排序结果放至tmp[mid+1...end]
        Merge(tmp, arr, start, mid, end);//将tmp[start...mid]和tmp[mid+1...end]合并至arr[start...end]
    }
}
void MergeSort(int *arr, int length)
{
    int *tmp=new int[length]();//分配辅助空间
    MSort(arr, tmp, 0, length-1);
    delete [] tmp;
}

/************************************************************************************/或者另外一种更加清楚的写法

void Merge(vector<int> &numbers, int begin, int mid, int end)
{
    int *arr=new int[end-begin+1];
    int i, j, k;
    for(i=begin, j=mid+1, k=0; i<=mid && j<=end; ++k)
    {
        if(numbers[i]<numbers[j])arr[k]=numbers[i++];
        else arr[k]=numbers[j++];
    }
    while(i<=mid)arr[k++]=numbers[i++];
    while(j<=end)arr[k++]=numbers[j++];
    for(i=begin; i<=end; ++i)numbers[i]=arr[i-begin];
    delete []arr;
}
void MergeSort(vector<int> &numbers, int begin, int end)
{
    if(begin<end)
    {
        int mid=(begin+end)/2;
        MergeSort(numbers, begin, mid);
        MergeSort(numbers, mid+1, end);
        Merge(numbers, begin, mid, end);
    }
}

 

8.基数排序

void RadixSort(int *arr, int length)
{
    vector<int> bucket[10];//数组0-9,设置10个桶
    int m=10;
    while(true)
    {
        bool flag=true;
        for(int idx=0; idx<length; ++idx)
        {
            int tmp=(arr[idx]%m)/(m/10);//m=10,取个位;m=100,取十位...
            bucket[tmp].push_back(arr[idx]);//按位放入桶中
            if(m<=arr[idx])flag=false;//循环终止条件
        }
        int k=0;
        for(int i=0; i<10; ++i)//将桶中元素倒出
        {
            for(size_t j=0; j<bucket[i].size(); ++j)
            {
                arr[k++]=bucket[i][j];
            }
            bucket[i].clear();
        }
        if(flag)break;
        m=m*10;//开始下一轮比较
    }
}

 

总结

排序方法 时间复杂度 空间复杂度 稳定性
最好 最坏 平均
直接插入排序 O(n) O(n2) O(n2) O(1) 稳定
希尔排序 O(n) O(n2) O(n1.3) O(1) 不稳定
简单选择排序 O(n) O(n2) O(n2) O(1) 不稳定
堆排序 O(n*log2n) O(n*log2n) O(n*log2n) O(1) 不稳定
冒泡排序 O(n) O(n2) O(n2) O(1) 稳定
快速排序 O(n*log2n) O(n2) O(n*log2n) O(log2n) 不稳定
归并排序 O(n*log2n) O(n*log2n) O(n*log2n) O(log2n)~O(n) 稳定
基数排序 O(d(r+n)) O(d(r+n)) O(d(r+n)) O(rd+n) 稳定
注:r代表关键字基数,d代表长度,n代表关键字个数

 

 

 

posted @ 2017-12-19 23:13  jeysin  阅读(185)  评论(0编辑  收藏  举报