简单的排序算法

常见的排序算法有以下7种:

  • 冒泡排序
  • 选择排序
  • 插入排序
  • 堆排序
  • 希尔排序
  • 归并排序
  • 快速排序

我们通常说的排序算法往往指的是内部排序算法,即数据记录在内存中进行排序

  • 排序算法大体可分为两种:
    1.一种是比较排序,时间复杂度为O(nlogn)~O(n^2),主要有冒泡排序,选择排序,插入排序,归并排序,堆排序,快速排序等
    2.另一种是非比较排序,时间复杂度可以达到O(n)
    除了排序算法的时间复杂度是我们比较关心的,还有一个就是排序算法的稳定性。
    排序算法稳定性的简单形式化定义为:如果Ai = Aj,排序前Ai在Aj之前,排序后Ai还在Aj之前,则称这种排序算法是稳定的。
接下来先介绍4种排序算法:
1.冒泡排序(这里可以从前向后冒泡,也可以从后向前冒泡)

(1)比较两个相邻元素,如果前一个比后一个大,就将两个元素进行交换
(2)依次向后进行比较操作,一趟冒泡下来,最后一个元素为当前这组数中的最大值
(3)继续再进行如上操作,进行第二次冒泡,但是最后一个元素不用进行比较,因为已经有序,以此类推第三次冒泡时,最后两个元素不需要比较
(4)重复上述操作,进行 元素个数-1 次冒泡,排序完成
如图是对一组数进行一趟冒泡排序的结果,按照此方法继续进行冒泡,就可以得到排序结果
这里写图片描述
下面是代码实现:

void BubbleSort(int array[],size_t size)
{
    if(size <= 1)
    {
        return;
    }
    //[0,i)表示有序区间
    //[i,size)表示待排序区间
    size_t i = 0;
    for(;i < size ;++i)
    {
        //这里采取的是从后向前冒泡
        size_t j = size -1;
        for(;j > i;--j)
        {
            if(array[j] < array[j-1] )
            {
                Swap(&array[j],&array[j-1]);
            }
        }
    }
    return;
}
2.选择排序

(1)第一次排序,第一个元素和后面的元素依次比较大小,如果第一个元素大的话就交换两个元素的位置,保证一次排序后第一个元素为这组数的最小值
(2)第二次排序,第二个元素和后面的元素依次比较大小,如果第二个元素大的话就交换两个元素的位置,保证第二次排序后第二个元素为剩下数中的最小值
(3)重复上述操作,就可以将该组数进行排序
如图是进行一次选择排序的结果,按照此方法继续进行选择排序就可以得到排序结果
这里写图片描述
下面是代码实现:

void SelectSort(int array[],size_t size)
{
    if(size <= 1)
    {
        return;
    }
    //[0,i)表示有序区间
    //[i,size)表示待排序区间
    size_t i = 0;
    for(; i < size ;++i)
    {
        size_t j = i + 1;
        for(; j < size;++j)
        {
            if(array[i] > array[j])
            {
                Swap(&array[i],&array[j]);
            }
        }
    }
    return;
}
3.插入排序

(1)从第一个元素,该元素可以被认为已经有序
(2)取出下一个元素,先保存起来,在已经排序的元素序列中从后向前比较
(3)如果当前元素大于要插入的元素,就把当前元素向后移
(4)重复步骤3,直到找到已排序的元素小于或等于新元素的位置
(5)将新元素插入到该位置
(6)重复上述操作,即可完成排序
如图是进行插入排序的过程
这里写图片描述
下面是代码实现:

void InsertSort(int array[],size_t size)
{
    if(size <= 1)
    {
        return;
    }
    //[0,i)表示有序区间
    //[i,size)表示待排序区间
    //插入排序是把前面的有序区间当做一个线性表
    //然后把 i_value 的值插入到线性表中合适的位置上
    size_t i = 1;
    for(; i < size;++i)
    {
        //此时存起来的意义是为了后面的搬运
        //一旦array[i]元素被单独保存起来了
        //array[i]数值就可以被修改了
        int i_value = array[i];
        //此时cur是辅助我们进行搬运的下标
        //从后向前遍历,找到合适的位置放 i_value 的位置
        size_t cur = i;
        for(;cur > 0;--cur)
        {
            //此处我们的初始情况就是拿线性表的最后一个元素和 i_value 比较
            //因此 array[cur-1]这里的 cur 取决于 cur 的初始位置
            if(array[cur-1] > i_value)
            {
                //进行搬运
                array[cur] = array[cur-1];
            }
            else
            {
                //说明已经找到了合适的位置
                break;
            }
        }
        //然后把i位置的元素插入到线性表的合适的位置上
        array[cur] = i_value;
    }
    return;
}
4.堆排序

(1)基于数组建立一个堆(如果是升序就建立大堆)
(2)循环的删除堆顶元素,将所有的元素都删除完毕,排序完成
(3)每次删除堆顶元素后,都对堆进行调整,这里有两种方法

方法一:把新元素放到数组的末尾,进行上浮式调整(从前往后遍历)
方法二:采用下沉式的调整(从后往前遍历)
起始位置就是堆的从后往前遍历的第一个非叶子节点
这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

如上给定一个数组建立一个堆已经完成,剩下的就是对堆进行删除堆顶元素,然后下沉式调整
下面是代码实现:

void AdjustDown(int array[],size_t size,size_t index)
{
    size_t parent = index;
    size_t child = 2 * index + 1 ;
    while(child < size)
    {
        if(child + 1 < size && array[child] < array[child+1])
        {
            child = child + 1;
        }
        if(array[parent] < array[child])
        {
            Swap(&array[parent],&array[child]);
        }
        parent = child;
        child = 2 * parent + 1;
    }
    return;
}
void HeapCreate(int array[],size_t size)
{
    if(size <= 1)
    {
        return;
    }
    size_t i = (size -1 -1) / 2;
    for(;i > 0;--i)
    {
        AdjustDown(array,size,i);
    }
    AdjustDown(array,size,0);
    return;
}
void HeapPop(int array[],size_t heap_size)
{
    if(heap_size <= 1)
    {
        return;
    }
    Swap(&array[0],&array[heap_size-1]);
    AdjustDown(array,heap_size - 1,0);
}
void HeapSort(int array[],size_t size)
{
    if(size <= 1)
    {
        return;
    }
    //1.基于数组建立一个堆(如果是升序,就建立大堆)
    HeapCreate(array,size);
    //2.循环的删除堆顶元素,将所有的元素都删除完毕,排序完成
    size_t i = 0;
    for(;i < size;++i)
    {
        //第二个参数表示数组中哪部分区间是符合堆的规则
        //第一个删除之前,[0,size)都是堆
        //第二次删除之前,[0,size-1)都是堆
        //第三次删除之前,[0,size-2)都是堆
        HeapPop(array,size-i);
    }
    return;
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值