插入排序,希尔排序,堆排序详解

本文将介绍三种排序算法--插入排序,希尔排序,堆排序。本文全部例子都是使用升序算法

  一.插入排序数组

   算法思想bash

    维护一个有序数组,将要插入的数据与有序数组自最后一个元素直到合适位置的数一一比较。ide

eg: 有序数组:1,3,5,6,7   如今待插入数据为2,那么他将会和7,6,5,3,依次做比较,当带插入数据小于有序数组最后的元素大小,则将该元素后移,直到待插入元素找到合适位置为止。学习

   代码实现spa

void InsertSort(int* a, int size)
02
{
03
    assert(a);
04
    for (int i = 0; i < size - 1; ++i)
05
    {
06
        int end = i;                                 //标识有序数组的最后一位
07
        int tmp = a[end + 1];
08
        while (end >= 0 && tmp < a[end])
09
        {
10
            a[end + 1] = a[end];                     //待插入数据比有序数组的最后一个数小,将有序数组最后一位向后移位
11
            --end;
12
        }
13
        a[end + 1] = tmp;
14
    }
15
}

总结orm

wKiom1dAlf6C8SCwAABJqI_Mfjc653.png    1.插入排序能够认为是间距为1的插入算法,说这个是为了待会儿更好的理解希尔排序。blog

    2.插入排序的时间复杂度为O(n^2);排序

    3.插入排序的空间复杂度为O(1);get

    4.具备稳定性


 排序算法的稳定性是指,通过排序算法排序的相同元素的相对位置不会发生改变。

  二.希尔排序

   算法思想

    希尔排序能够认为是插入排序的加强版,由于,他加入了一个预排的过程,即在实现间距为1的插入算法以前,他已经预先将间距为gap(gap一直减减直到>0)的数组排列过了。因此,当进行gap = 1的插入排序以前使得待排序数组已经高度接近有序,使得此次进行的gap = 1的排序的时间复杂度,能够小于O(N^2)(gap = 1的插入排序,最好状况的时间复杂度为O(1),前面的预排过程正是出于这个目的)。

   代码实现

//希尔排序
02
void ShellSort(int* a,size_t size)
03
{
04
    assert(a);
05
    int gap = size / 2;
06
    while (gap > 0)
07
    {
08
        for (int i = 0; i < size - gap; ++i)
09
        {
10
            int end = i;                                
11
            int tmp = a[end + gap];
12
            while (end >= 0 && tmp < a[end])
13
            {
14
                a[end + gap] = a[end];                    
15
                end -= gap;
16
            }
17
            a[end + gap] = tmp;
18
        }
19
        --gap;
20
    }
21
}

总结

wKioL1dAmcezLq9UAAA-_4AF_-0959.png 上图为gap = 5 的时候的预排效果图

 1.希尔排序预排的思想和插入排序的思想是一致的,只是,他把原数组分红不一样的区间。

 2.希尔排序的时间复杂度为O(N^2),空间复杂度为O(1);

 3,具备不稳定性


 三.堆排序

  算法思想

wKiom1dAmjOj5RrrAABza1LyiDI524.png代码实现

void AdjustDown(int* a, size_t size, int parent)
02
{
03
    assert(a);
04
    int child = parent * 2 + 1;
05
    while (child<size)
06
    {
07
        if (child+1<size && a[child] < a[child + 1])
08
            ++child;
09
        if (a[parent] < a[child])
10
        {
11
            swap(a[parent], a[child]);
12
            parent = child;
13
            child = parent * 2 + 1;
14
        }
15
        else
16
        {
17
            break;
18
        }
19
         
20
    }
21
}
22
void HeapSort(int* a,size_t size)
23
{
24
    assert(a);
25
    //建堆
26
    for (int i = (size - 2) / 2; i >= 0; --i)  //从第一个非叶子节点开始调
27
    {
28
        AdjustDown(a, size, i);
29
    }
30
    for (size_t i = 0; i < size; ++i)
31
    {
32
        swap(a[0], a[size - 1 - i]);
33
        AdjustDown(a, size - i - 1, 0);
34
    }
35
}

总结


 1.时间复杂度为O(N*lgN),空间复杂度为O(1);


 2.具备不稳定性




 以上就是本人在学习过程当中的一些经验总结。固然,本人能力有限,不免会有纰漏,但愿你们能够指正。

相关文章
相关标签/搜索