关于排序算法小结

//插入排序

void InserSort(int arr[], int len)
{
    int temp;
    int i, j;
    for(i = 1;i < len;i++)
    {
        temp = arr[i];
        for(j = i - 1;j >= 0 && arr[j] > temp;j--)
        {
            arr[j + 1] = arr[j];
        }
        arr[j + 1] = temp;
    }
}

插入排序将数组中的一个元素拿出来,然后将它和它前面的元素进行比较,如果不等则调整顺序

代码空间复杂度O(1)
代码时间复杂度:
最好情况:O(n)
最坏情况:O(n^2)
平均情况:O(n^2)
算法稳定


//二分插入排序

//二分插入排序
void BinaryInsertSort(int arr[], int len)
{
    for(int i = 1; i < len; i++)
    {
        int get = arr[i];//拿到新牌
        int left = 0;//左边的手牌已经排好序
        int right = i - 1;//从右边开始
        while(left <= right)//采用二分法定位新牌的位置
        {
            int mid = ((right - left) >> 1) + left;
            if(arr[mid] > get)
                right = mid - 1;
            else
                left = mid + 1;
        }
        for(int j = i - 1; j >= left; j--)
        {
            arr[j + 1] = arr[j];
        }
        arr[left] = get;
    }
}

代码空间复杂度O(1)
代码时间复杂度:
最好情况:O(nlogn)
最坏情况:O(n^2)
平均情况:O(n^2)
算法稳定


//希尔排序

void Shell(int arr[],int len, int dk)
{
    int temp;
    int i,j;
    for(i = dk;i < len;i++)
    {
        temp = arr[i];
        for(j = i - dk;j >= 0 && arr[j] > temp; j -= dk)
        {
            arr[j + dk] = arr[j];
        }
        arr[j + dk] = temp;
    }
}

void ShellSort(int arr[],int len,int dk[],int dk_len)
{
    for(int i = 0;i < dk_len;i++)
    {
        Shell(arr,len,dk[i]);
    }
}

希尔排序是一种优化的插入排序,它引入了一种步长的概念,在步长为1时候,它就是一个插入排序
另外,希尔排序的步长最好选择素数,避免元素比较重复,并且步长最终需要变为1
算法空间复杂度:O(1)
算法时间复杂度:
最好情况下:O(n)
最坏情况下:O(n^2)
平均情况下:O(n^2)
算法不稳定


//冒泡排序

void BubbleSort(int arr[], int len)
{
    int temp,flag = 0;
    for(int i = 0; i < len - 1; ++i)
    {
        flag = 0;
        for(int j = 0; j < len - 1; ++j)
        {
            if(arr[j] > arr[j + 1])
            {
                temp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = temp;
                flag = 1;
            }
        }
        if(flag == 0)
        {
            break;
        }
    }
}

算法空间复杂度:O(1)
算法时间复杂度:
最好情况下:O(n)
最坏情况下:O(n^2)
平均情况下:O(n^2)
算法稳定


//定向冒泡排序

//鸡尾酒排序,前到后后到前
void CocktailSort(int arr[], int len)
{
    int left = 0;
    int right = len - 1;
    while(left < right)
    {
        for(int i = left; i < right; ++i)//第一轮找出一个最大的
        {
            if(arr[i + 1] < arr[i])
            {
                Swap(arr[i + 1], arr[i]);
            }
        }
        right--;
        for(int i = right; i > left; i--)//第二轮找一个最小的
        {
            if(arr[i - 1] > arr[i])
            {
                Swap(arr[i - 1], arr[i]);
            }
        }
        left++;
    }
}

算法空间复杂度:O(1)
算法时间复杂度:
最好情况下:O(n)
最坏情况下:O(n^2)
平均情况下:O(n^2)
算法稳定


//选择排序

void SelectSort(int arr[], int len)
{
    int min_index;
    int tmp;
    for(int i = 0; i < len - 1; i++)
    {
        min_index = i;
        for(int j = i + 1; j < len; j++)
        {
            if(arr[min_index] > arr[j])
            {
                min_index = j;
            }
        }
        if(arr[min_index] < arr[i])
        {
            tmp = arr[i];
            arr[i] = arr[min_index];
            arr[min_index] = tmp;
        }
    }
}

算法空间复杂度:O(1)
算法时间复杂度:
最好情况下:O(n^2)
最坏情况下:O(n^2)
平均情况下:O(n^2)
算法不稳定


//堆排序

void swap(int &a, int &b)
{
    int temp;
    temp = a;
    a = b;
    b = temp;
}

void HeapAdjust2(int arr[], int i, int len)
{
    int lr = 2 * i + 1;
    int lc = 2 * i;
    
    if(lc > len)
    {
        return;
    }
    if(i * 2 + 1> len)
    {
        lr = lc;
    }

    (arr[i] > arr[lc])?((arr[i] > arr[lr])?NULL:swap(arr[i], arr[lr]),HeapAdjust(arr,lr,len)):((arr[lc] > arr[lr])?swap(arr[i], arr[lc]), HeapAdjust(arr, lc, len):swap(arr[i], arr[lr]),HeapAdjust(arr, lr, len));
}

void HeapAdjust(int arr[], int i,int len)
{

    int temp;
    for(int j = i * 2; j <= len; j *= 2)
    {
        if(j < len && arr[j] < arr[j + 1])
        {
            j++;
        }
        //j出来时是左右子树最大值的下标
        if(arr[j] <= arr[i])
        {
            break;
        }
        temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
        i = j;
    }
}

void HeapSort(int arr[], int len)
{
    int temp;

    //建堆
    for(int i = len / 2; i > 0; --i)
    {
        HeapAdjust(arr, i, len);
    }

    //排序
    for(int i = len; i > 0; --i)
    {
        temp = arr[i];
        arr[i] = arr[1];
        arr[i] = temp;
        HeapAdjust(arr, 1, i - 1);
    }
}

算法空间复杂度:O(1)
算法时间复杂度:
最好情况下:O(nlogn)
最坏情况下:O(nlogn)
平均情况下:O(nlogn)
算法不稳定


//计数排序

//计数排序
#define Max 100
int c[Max];

void CountingSort(int arr[], int len)
{
    //填充c数组
    memset(c, 0, sizeof(int)* Max);
    for(int i = 0; i < len; ++i)
    {
        c[arr[i]]++;
    }
    //调整c数组
    for(int i = 1; i < Max; ++i)
    {
        c[i] += c[i - 1];
    }

    int *b = (int *)malloc(sizeof(int) * len);
    for(int i = len - 1; i >= 0; --i)//从后往前扫保证计数的稳定性
    {
        b[--c[arr[i]]] = arr[i];
    }
    memmove(arr, b, sizeof(int)* len);
    delete[] b;
}

算法空间复杂度:O(n+k)
算法时间复杂度:
最好情况下:O(n+k)
最坏情况下:O(n+k)
平均情况下:O(n+k)
算法稳定


//基数排序

#define SIZE 10

// 返回number第digit位数字
inline int GetDigit(int num, int digit)
{
    for(int i = 0; i < digit; i++)
    {
        num /= 10;
    }
    return num % 10;
}

// 根据元素的第dig位来进行计数排序
void Radix(int arr[], int len, int dig)
{
    int bucket[10][SIZE] = {0};
    int count[10] = {0};

    for(int i = 0; i < len; i++)
    {
        int fig_num = GetDigit(arr[i], dig);
        bucket[fig_num][count[fig_num]] = arr[i];
        count[fig_num]++;
    }

    int k = 0;
    for(int i = 0; i < 10; i++)
    {
        for(int j = 0; j < count[i]; j++)
        {
                arr[k++] = bucket[i][j];
        }
    }
}

inline int FindMaxDigit(int arr[], int len)
{
    int max = arr[0];
    for(int i = 1; i < len; i++)
    {
        if(max < arr[i])
        {
            max = arr[i];
        }
    }
    return log10(max) + 1;
}

void RadixSort(int arr[], int len)
{
    for(int i = 0; i < FindMaxDigit(arr, len); i++)
    {
        Radix(arr, len, i);
    }
}

基数排序可以建桶用个队列,这里用的数组有点浪费空间
算法空间复杂度:O(桶数*桶长度+数组长度)
算法时间复杂度:
最好情况下:O(数组长度) //(最好情况下最大数字位数为1)
最坏情况下:O(数组长度 + 数组中最大数的位数 X (数组长度 X 数组最大位数))
平均情况下:O(数组长度 + 数组中最大数的位数 X (数组长度 X 数组最大位数))
算法稳定


//归并排序

#include<iostream>
using namespace std;

template<class Type>
void Print2Array(Type s, int n, int m)
{
    for(int i = 0;i<n;++i)
    {
        for(int j = 0;j<m;++j)
        {
            cout << setw(3) << s[i][j];
        }
        cout << endl;
    }
    cout << endl;
}
template<class Type>
void PrintArray(Type *ar, int n)
{
    for(int i = 0;i<n;++i)
    {
        cout << ar[i] << " ";
    }
    cout << endl;
}

template<typename T>
void Copy(T *sd, T *si, int left, int right)
{
    for(int i = left; i <= right; ++i)
    {
        sd[i] = si[i];
    }
}
template<typename T>
void Merge(T *sd, T *si, int left, int m, int right)
{
    int indexA = left;
    int indexB = m + 1;
    int k = left;
    while(indexA <= m && indexB <= right)
    {
        sd[k++] = si[indexA] < si[indexB]?si[indexA++]:si[indexB++];
    }

    while(indexA <= m)
    {
        sd[k++] = si[indexA++];
    }

    while(indexB <= right)
    {
        sd[k++] = si[indexB++];
    }
}
template<typename T>
void MSort(T *ar, T *br, int left, int right)
{
    if(left < right)
    {
        int m = (right - left) / 2 + left;
        MSort(ar, br, left, m);
        MSort(ar, br, m + 1, right);
        Merge(br, ar, left, m, right);
        Copy(ar, br, left, right);
    }
}
template<typename T>
void MergeSort(T *ar, int n)
{
    if(ar != nullptr && n > 0)
    {
        T *br = new T[n];
        MSort(ar, br, 0, n - 1);
        delete[]br;
    }
}

template<typename Ty>
void NiceMerge(Ty *ds, Ty si, int n, int size)
{
    int i = 0;
    for(; i + 2 * size <= n;i += 2 * size)
    {
        Merge(ds, si, i, i + size - 1, i + 2 * size - 1);
    }
    if(n - 1 > i + size)
    {
        Merge(ds, si, i, i + size - 1, n - 1);
    }
    else
    {
        for(int j = i; j < n; ++j)
        {
            ds[j] = si[j];
        }
    }
}
template<typename Ty>
void NiceMergeSort(Ty *ar, int len)
{
    if(ar != nullptr && len > 0)
    {
        Ty *br = new Ty[len];
        int s = 1;//每次递归的长度,开始是一个一个,到两个两个,到四个四个,二倍增长
        while(s < len)
        {
            NiceMerge(br, ar, len, s);
            s += s;
            NiceMerge(ar, br, len, s);
            s += s;
        }
        delete[] br;
    }
}

int main()
{
    int ar[] = {23,45,78,12,19,57,90,78};
    int n = sizeof(ar) / sizeof(ar[0]);
    PrintArray(ar, n);
    //MergeSort(ar, n);
    NiceMergeSort(ar, n);
    PrintArray(ar, n);

    return 0;
}

算法空间复杂度:O(n)
算法时间复杂度:
最好情况下:O(nlogn)
最坏情况下:O(nlogn)
平均情况下:O(nlogn)
算法稳定


好久没来填坑了,其实我今天也没法把这个填完。。。。。之后有时间继续吧,补上快排

**//快速排序**
-----
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
//普通快排
//优化1:最坏情况   随机选取基准点值
//优化2:三分取中法  
//优化3:数据量小时  用插排
//优化4:聚集优化   和基准点相同的数据剔除
void Swap(int arr[], int, int);

void findSecondMaxNumber(int arr[], int low,int mid, int high)
{
    if (arr[mid] > arr[high])
    {
        Swap(arr, mid, high);
    }
    if (arr[low] < arr[mid])
    {
        Swap(arr, low, mid);
    }
    if (arr[low] > arr[high])
    {
        Swap(arr, low, high);
    }
}
void Swap(int arr[], int fristIndex, int secondIndex)
{
    int tmp = arr[fristIndex];
    arr[fristIndex] = arr[secondIndex];
    arr[secondIndex] = tmp;
}
void Gather(int arr[], int low, int bounIndex, int high, int *left, int *right)
{
    if (low < high)
    {
        int count = bounIndex - 1;
        for (int i = bounIndex - 1; i >= low; i--)
        {
            if (i != count && arr[i] == arr[bounIndex])
            {
                Swap(arr, count, i);
                count--;
            }
        }
        *left = count;
        count = bounIndex + 1;
        for (int i = bounIndex + 1; i <= high; i++)
        {
            if (i != count && arr[i] == arr[bounIndex])
            {
                Swap(arr, count, i);
                count++;
            }
        }
        *right = count;
    }
}
int Parition(int arr[], int low, int high)
{
    int tmp = arr[low];
    while (low < high)
    {
        //1 2 3 4 5 6
        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 InsertSort(int arr[], int low,int high);
void QSort(int arr[], int low, int high)
{
    if (low < high)
    {
        //if (high - low + 1 < 20)
        //{
        //    InsertSort(arr, low, high);
        //    return;
        //}
        //Swap(arr, low, rand() % (high - low)+low);
        //findSecondMaxNumber(arr, low, (high-low)/2+low, high);
        int boundKey = Parition(arr, low, high);
        int left = boundKey - 1;
        int right = boundKey + 1;
        Gather(arr, low, boundKey, high, &left, &right);
        QSort(arr, low, left);
        QSort(arr, right, high);
        //QSort(arr, low, boundKey - 1);
        //QSort(arr, boundKey + 1, high);
    }
}
void QuickSort(int arr[], int len)
{
    QSort(arr, 0, len - 1);
}

算法空间复杂度:O(logn)
算法时间复杂度:
最好情况下:O(nlogn)
最坏情况下:O(n^2)
平均情况下:O(nlogn)
算法不稳定


暂时就这样子了,加上了定向冒泡排序和二分插入以及计数,久违的把这个做完了,路漫漫兮~


且行且歌_C
62 声望8 粉丝

逝者如斯夫,不舍昼夜