排序一之插入排序和希尔排序

1.插入排序
插入排序(Insertion Sort)是一种简单直观的排序算法。它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。插入排序在实现上,通常采用in-place排序(即只需用到O(1)的额外空间的排序),因而在从后向前扫描过程中,需要反复把已排序元素逐步向后挪位,为最新元素提供插入空间。
算法描述:
1.从第一个元素开始,该元素可以认为已经被排序
2.取出下一个元素,在已经排序的元素序列中从后向前扫描
3.如果该元素(已排序)大于新元素,将该元素移到下一位置
4.重复步骤3,直到找到已排序的元素小于或者等于新元素的位置
5.将新元素插入到该位置后
6.重复步骤2~5
动画演示:
这里写图片描述

实现代码:

#include<iostream>
using namespace std;
#include<cassert>
void InsertSort(int array[], int len)
{
    assert(array && len > 0);

    for(int i = 1; i < len ;++i) //只有一个元素的时候有序,所以这里从1开始
    {
        int temp = array[i];  //记录当前待插入的元素
        int end = i-1;  //最后一个有序元素的下标

        while(end >=0 && array[end]>temp) //找要插入的位置
        {
            array[end+1] = array[end];
            end--;
        }
        array[end+1] = temp;
    }
}

//改良版:上面那个版本排一个元素就需要从尾开始比较,比较次数太多了,我们可以先用二分法找出待插入的位置,整体搬移元素
void InsertSort2(int array[], int len)
{
    assert(array && len > 0);

    for(int i = 1; i < len; ++i)
    {
        int temp = array[i];
        int end = i-1;
        int left = 0;
        int right = end;

        while(left <= right)
        {
            int mid = (left+right)/2;
            if(array[mid] > temp)
                right = mid-1;
            else 
                left = mid+1;
        }//left就是我们要找的位置

        //搬移元素
        while(end >=0 && end >=left )
        {
            array[end+1] = array[end];
            end--;
        }
        array[left] = temp;

    }



}


void Print(int array[], int size)
{
    for(int i = 0; i < size; ++i)
    {
        cout << array[i] << " ";
    }
    cout <<endl;
}

int main()
{
    int array[] = {12,54,32,82,41,9,30,56};
    int size = sizeof(array)/sizeof(array[0]);

    //InsertSort(array, size);
    InsertSort2(array, size);

    Print(array, size);

    cout << "hello..."<<endl;
    return 0;
}

插入排序:
最好的情况下:正序有序(从小到大),这样只需要比较n次,不需要移动。因此时间复杂度为O(n)
最坏的情况下:逆序有序,这样每一个元素就需要比较n次,共有n个元素,因此实际复杂度为O(n*n)
平均情况下:O(n*n)
稳定的算法
适用场景:插入排序对于部分有序的数组十分高效,也很适合小规模的数组。
折半查找只是减少了比较次数,但是元素的移动次数不变,所以时间复杂度为O(n^2)是正确的 二分插入排序与序列初始状态无关。

  • 希尔排序
    希尔排序,也称为递减增量排序算法,是插入排序的一种高效的改进版本
    算法描述:
    1.先取一个正整数 d1(d1 < n),把全部记录分成 d1 个组,所有距离为 d1 的倍数的记录看成一组,然后在各组内进行插入排序
    2.然后取 d2(d2 < d1)
    3.重复上述分组和排序操作;直到取 di = 1(i >= 1) 位置,即所有记录成为一个组,最后对这个组进行插入排序。一般选 d1 约为 n/2,d2 为 d1 /2, d3 为 d2/2 ,…, di = 1。

动画演示:
这里写图片描述
这里写图片描述
代码实现:

#include<iostream>
using namespace std;
#include<cassert>

//希尔排序其实就是分组排序,但是每一组排序原理还是插入排序。
void ShellSort(int array[], int len)
{
    assert(array && len > 0);

    int gap = len;

    while(gap > 1)
    {
        gap = gap / 3 +1;  //分组间距。

        for(int i = gap; i < len; ++i)
        {
            int temp = array[i];
            int end = i-gap;

            while(end >= 0 && array[end] > temp)
            {
                array[end+gap] = array[end];
                end = end -gap;
            }

            array[end+gap] = temp;
        }
    }
}


void Print(int array[], int size)
{
    for(int i = 0; i < size; ++i)
    {
        cout << array[i] << " ";
    }
    cout <<endl;
}

int main()
{
    int array[] = {12,54,32,82,41,9,30,56};
    int size = sizeof(array)/sizeof(array[0]);

    ShellSort(array, size);

    Print(array, size);

    cout << "hello..."<<endl;
    return 0;
}

希尔排序是插入排序的一个改良,它其实是一个分组排序, 不稳定的算法
最好情况 O(n),最坏情况o(n*n) 平均情况o(n^1.3~n^1.6)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值