排序算法小结(1) 插入排序

马上就要毕业面试了可是发现很多数据结构的基本知识掌握的都还不是很好,特别是各种排序算法。
听说是面试必问的题,弄得我虚的不行,今天就来写个博客对各种排序算法做一个总结。 

1.插入排序–直接插入排序
先上代码

void InsertSort(int a[],int n)
{
    if(a==NULL || n==0)
        return;//检查参数的合法性
    for(int i=1;i<n;++i)
    {
        //i表示当前要插入有序序列的元素
        int j=i-1;//j表示数组中已有序最后一个元素
        int value = a[i];//需要一个空间存放待插入的数字
        for(;j>-1;--j)
        {
            if(value < a[j])
                a[j+1] = a[j];//大于插入的数字,后移
            else
                break;//退出循环时,为插入位置的前一个位置
        }
        a[j+1] = value;//插入数据
    }
}

算法的思路比较简单:每次向数组已有序的序列中插入一个新数字,并使有序序列任保持有序。具体的过程代码注释描述的比较清楚,就不写了。
从上面过程可以看出:
1.简单插入排序是:稳定的。因为如果插入的数字相等,会被放到相等数字的后面,保持了排序前后的相对位置关系。
2.时间复杂度为O(n^2),两层循环;在基本有序的情况下时间复杂度可以达到O(n),因为内层循环会直接退出。
3.空间复杂度为O(1),使用了一个临时变量value。

2.插入排序–希尔排序

这个排序是我一直没有仔细研究过得,主要原因就是代码有些看不懂,分组后的插入排序跟一些分析完全不一样嘛。今天仔细研究一下,发现其实是一样的,看来以后看代码还是要认真些,遇到不懂的一定不能放弃。看代码:

void ShellInsertSort(int *a,int n, int dk)
{//希尔排序中插入排序的部分,与简单插入排序的结构相同,只是将步长切换为dk
    if(dk == 0)
        return;
    for(int i=dk;i<n;++i)
    {
        int j = i-dk;//纠结的在这里,一直以为应该是先分组,再执行简单插入排序。
        //其实程序的执行过程是按照一定的步长,一边移动一边插入排序,其实这也更加符合简单插入排序的框架。(自己真挫呀!)
        int value = a[i];
        for(;j>-1;j -= dk)
        {
            if(value < a[j])
                a[j+dk] = a[j];
            else
                break;
        }
        a[j+dk] = value;
    }
}
void ShellSort(int *a,int n )
{//希尔排序
    if(a == NULL || n == 0)
        return;
    int dk = n;
    while((dk /= 2))//不断的缩小步长直至 为1
        ShellInsertSort(a,n,dk);
    display(a,n);
}

从代码来看插入排序还是比较简单的:
1.对待排序数组,按照一定的步长dk,执行简单插入排序;
2.缩小dk,重复步骤1,直至dk=1.
从上诉思路可以看出应该将插入排序的代码分成两个部分,ShellInsertSort()执行简单插入排序,ShellSort()缩小dk,并执行ShellInsertSort()。
时间空间复杂度分析:
1.希尔排序:不稳定。很明显,当两个相同的数字,在分组时在不同的组内,那么两个数组的相对位置是有可能发生变化的。
2.时间复杂度:这个书上说分析比较难,我也只能在这里定性分析一下。结合简单插入排序的时间复杂度介于O(n^2)和O(n),当数据有序的元素越多简单插入排序的时间复杂度会越低,可以把希尔排序的dk!=1的过程想象成是在构造一个相对有序的序列,这样执行dk=1时时间复杂度就接近O(n)。当然最后的结论是希尔排序时间复杂度为O(n^1.3),这个怎么来的还有待研究。还有一点比较重要,希尔排序的时间复杂度会受到序列是否有序影响。
3.空间复杂度:这个应该是O(1)吧,有一个零时变量value。

插入排序就到这吧,先把基本的掌握了,变形的就不怕了~

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值