四种简单排序的详细分析与总结

直接插入排序:

  直接插入排序就是就是从end的下一位挑选一个数字不断地向前进行插入,整个过程伴随着end的位置从0置end-1,该无序数列也逐渐成为了一个有序数列!思想还是比较简单的,当原合越接近有序时,直接插入排序算法的效率越高。时间复杂度是0N的二次方,是一种比较稳定的排序方式!

  当写直接插入排序的代码时,我们可以先写单次循环的代码,最后再通过在外部控制end的位置写一个大循环 !

int InsertSort(int *a, int n)
{
    for (int i = 0; i <= n - 2; i++)
    {
        int end = i;
        int tmp = a[end + 1]
        while(end>=0){
            if (a[end] > a[tmp])
            {
                a[end + 1] = a[end];
                --end;
            }
            else
                break;
        }
    }
    a[end + 1] = tmp;
}

这是插入排序的代码,其中需要注意的点在于先写单次循环,而后再整体大循环,可能很多人会对a[end+a]=tmp这一句比较疑惑。其实当,end'一直减减到头会导致,end出现在-1这个位置上,tmp自然而然就会插入到end=0的位置上上。

希尔排序:

  希尔排序说白了就是一种优化后的直接插入排序,不同的点在于他对数组进行了分组操作,复杂度有所减小,可以达到ON的一点三次方。希尔排序会对整个数据进行预排序->使数组接近于有序,而后会进行直接插入排序。

  预排序:数组进行分组,间隔是gap的分为一组,分别进行排序,分别让着gap组数据进行插入排序。gap越小,会越接近于有序,跳的越慢。gap越大,越不接近于有序,跳的越快。当多次进行预排序,gap会变得越来越小。当gap=1时,显而易见他就是一个直接插入排序!

int ShellSort(int *a, int n)
{
    int gap = n;
    while (gap>1)
    { 
        gap = gap / 3 + 1;
    for (int i = 0; i <= n - gap; i++)
    {
        int end = i;
        int tmp = a[end + gap]
        while(end>=0){
            if (a[end] > a[tmp])
            {
                a[end + gap] = a[end];
                end -= gap;
            }
            else
                break;
        }
    }
    a[end + gap] = tmp;
}

  这就是希尔排序的算法代码,可以看出很明显就是对直接插入排序的变形,增加了一个gap变量,用于进行分组!gap=gap/3+1这里3不能写成二,一旦写成2,会出现死循环的情况!为什么要进行+1操作呢,保证不伦n多大,最终都可以跳回到gap=1,从而进行直接插入排序!这个算法比较巧妙的地方在于,gap个间隔为gap的组进行同时交插排序!

选择排序:

  一次选择两个数,最小的数放在第一个位置,最大的数放在最后的一个位置!应该去找到最小数与最大数的下标,而不是找到数,这样能防止覆盖!

void SelectSort(int *a, int n){
    int begin = 0, end = n - 1;
    while (begin < end)
    {//[begin,end]中选出一个最小的,选出一个最大的下标!
        int mini = begin, maxi = end;
        for (int i = begin; i <= end; ++i)
        {
            if (a[i]>a[maxi])
                maxi = i;
            if (a[i] < a[mini])
                mini = i;
        }
        Swap(&a[begin], &a[mini]);
        if (begin == maxi){
            maxi = mini;
        }
        Swap(&a[end], &a[maxi]);
        ++begin;
        --end;
    }

}

这种排序特别简单,需要注意的点就是

   if (begin == maxi){
            maxi = mini;

这一块,当出现情况开头第一个数字是最大的时候,会对begin与mini进行交换,但是这个时候maxi位置且没有发生变化,直接导致后一步end与maxi交换时出现,刚换过去的mini指向的最小值被交换到了数组的end端!

冒泡排序:

  一次又一次的向下沉底,下面是基本代码

void BubbleSort(int *n, int n)
{
    for (int end = n - 1; end > 0;--end){
        int flag = 0;
        for (int i = 0, i < end; ++i)
        {
            if (a[i] > a[i + 1]){
                Swap(&a[i], a[i + 1]);
                flag = 1;
            }
        }
        if (flag == 0)//说明并没有发生交换
            break;
    }
}
对于这个排序我想说的就是这个flag这一点新意,它是对冒泡排序的一种优化,当一次 内循环没有发生任何交换时(flag值恒为0)那么就可以直接跳出,这种方法对于特定的数组提高了不小的效率!

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值