常用排序算法总结

本文详细介绍了排序算法,包括插入排序、归并排序、选择排序、桶排序和快速排序,分析了它们的时间复杂度和性能特点。插入排序在最好情况下时间复杂度为O(n),最坏为O(n^2);归并排序始终保持O(nlogn);选择排序的时间复杂度为O(n^2);桶排序的时间复杂度为O(n);快速排序在最好和平均情况下为O(nlogn),最坏为O(n^2)。
摘要由CSDN通过智能技术生成

1.排序算法

1.1 插入排序

1.1.1 概念

1.1.2 代码

void insertionSort(int arr[], int len)
{
    int insertPosi;

    for (int i = 0; i < len; i++)
    {
        insertPosi = 0;                     //can't find the bigger position then keep the insertPosi 0
        //find the insert position
        for (int j = i - 1; j >= 0; j--)
        {
            if (arr[j] <= arr[i])
            {
                insertPosi = j + 1;         //insert at arr[j + 1], minimum of inserPosi is 1 int the loop;
                break;
            }
        }


        //same position as i, just keep it
        if (insertPosi == i)
            continue;


        //copy from [j + 1, i - 1] -> [j + 2, i]
        //namely copy from [insertPosi, i) -> [insertPosi + 1], i + 1)
        int temp = arr[i];
        for (int k = i - 1; k >= insertPosi; k--)
        {
            arr[k + 1] = arr[k];
        }
        arr[insertPosi] = temp;
    }
}

1.1.3 时间复杂度分析

查找插入位置的效率 在 O(1)~O(n)浮动
1)当输入序列已经有序时,该算法中的查找插入位置仅需O(1)时间,
即第一次判断 arr[j] <= arr[i],就成立了,就完成搜索了;
累计需要O(n)的时间,n*O(1)。
2)当输入序列完全逆序,则各次查找插入位置需要线性时间;
即每次都要判断线性长度次,比如将第i个元素插入到前面[0,i)的有序
序列中,需要搜索 i-1 次。
这样搜索完所有的长度,累计需要 O(n2) 时间,1+2+3+……+n的级别。

另外,向后复制的次数和搜索的向前遍历的次数是一样的,所以,总的时间是
2倍于搜索所需时间,常数2可以抹去。

总结
1)在等概率条件下,平均仍需要 O(n2) 时间。
2)输入敏感性很强,时间取决于逆序对的数目!!!

1.2 归并排序

1.2.1 概念


1.2.2 代码

/***************sort 2: mergeSort***************
***********************************************/
void mergeSort(int arr[], int len)
{
    mergeSortCore(arr, 0, len);
}

/*
[lo, hi)
*/
void mergeSortCore(int arr[], int lo, int hi)
{
    if (hi - lo < 2) return;
    int mi = (lo + hi) / 2;
    mergeSortCore(arr, lo, mi);
    mergeSortCore(arr, mi, hi);
    merge(arr, lo, mi, hi);
}


/*
二路有序数组的归并,
[lo, mi)
[mi, hi)

复杂度分析:
每经过一次迭代,j和k至少有一个会+1,
merge总体迭代不会超过O(n)
*/
void merge(int arr[], int lo, int mi, int hi)
{
    int* A = arr + lo;
    int lb = mi - lo;
    int* B = new int[lb];

    for (int i = 0; i < lb; B[i] = A[i++]);

    int lc = hi - mi;
    int* C = arr + mi;

    //1.精简实现
    //循环条件是复制出来的B序列还没全部插入排序
    //如果B已经全部插入排序,C序列本身与A序列共享内存,不需要再做搬运复制工作
    for (int i = 0, j = 0, k = 0; j < lb; )
    {
        //C序列还没全部插入,并且比B序列当前的小
        if (k < lc && C[k] < B[j])
            A[i++] = C[k++];
        //C序列已经全部插入,或者 B序列当前的比C序列的小
        if (lc <= k || B[j] <= C[k])
            A[i++] = B[j++];
    }
    //2.复杂实现
    // for (int i = 0, j = 0, k = 0; (j < lb) || (k < lc); )
    // {
   
    //  if ((j < lb) && (!(k < lc) || (B[j] <= C[k])))
    //      A[i++] = B[j++];
    //  if ((k < lc) && (!(j < lb) || (C[k] < B[j])))
    //      A[i++] = C[k++];
    // }

    delete [] B;
}

1.2.3 时间复杂度分析

归并排序

O(nlogn) 是根据递推式得出来的,根据分而治之策略,
T(n)

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值