排序算法之插入排序

直接插入排序:
原理:
每步将一个待排序的纪录,按其关键码值的大小插入前面已经排序的文件中适当位置上,直到全部插入完为止。

排序算法之插入排序_第1张图片
1、保存0
2、5,3,2,1分别向后移动一个位置
3、将0放到第一个位置

排序算法之插入排序_第2张图片
1、保存4
2、将6,5分别向后移动一个位置
3、将4放到3的后面

代码:

void InsertSort(int *arr, size_t size)
{
assert(arr);
for (size_t i = 0; i < size-1; i++)
{
if (arr[i]>arr[i + 1])
{
int tmp = arr[i + 1];
int j = i;
while (tmp < arr[j] && j >= 0)
{
arr[j + 1] = arr[j];
--j;
}
arr[j + 1] = tmp;
}
}
}

//直接插入排序优化,在寻找插入点的时候因为前面的数已经排好了次序
//所以可以使用二分查找加快查找效率

void BinaryInsertSort(int *arr, int size)
{
assert(arr);
for (int i = 0; i < size-1; i++)
{
if (arr[i]>arr[i + 1])
{
int tmp = arr[i + 1];
int mid = 0;
int left = 0;
int right = i;
while (left <= right)
{
mid = (left+right)/2;
if (arr[mid]>tmp)
{
right = mid - 1;
}
else if (arr[mid]<tmp)
{
left = mid + 1;
}
else
{
break;
}

}
for (int j = i+1; j > right+1; j--)
{
arr[j] = arr[j-1];
}
arr[right+1] = tmp;
}
}
}

总结:
1、时间复杂度O(n2)
2、最差情况:反序,需要移动n*(n-1)/2个元素
3、最好情况:正序,不需要移动元素
插入排序不适合对于数据量比较大的排序应用。但是,如果需要排序的数据量很小,例如,量级小于千,那么插入排序还是一个不错的选择。

希尔排序

希尔排序,也称递减增量排序算法,是插入排序的一种更高效的改进版本。希尔排序是非稳定排序算法。

希尔排序是基于插入排序的以下两点性质而提出改进方法的:
插入排序在对几乎已经排好序的数据操作时,效率高,即可以达到线性排序的效率但插入排序一般来说是低效的,因为插入排序每次只能将数据移动一位

算法实现:
希尔排序通过将比较的全部元素分为几个区域来提升插入排序的性能。
这样可以让一个元素可以一次性地朝最终位置前进一大步。然后算法再取越来越小的步长进行排序,
算法的最后一步就是普通的插入排序,但是到了这步,需排序的数据几乎是已排好
的了(此时插入排序较快)。

void ShellSort(int *arr, int size)
{
    assert(arr);
    int gap = size / 2;
    for (gap; gap > 0; gap /= 2)
    {
        for (int i = 0; i < size - gap; i++)
        {
            for (int j = i; j >= 0 && arr[i] > arr[gap + i]; j = j - gap)
                {
                    swap(arr[j], arr[j + gap]);
                }
        }
    }
}

你可能感兴趣的:(移动,插入排序,希尔排序,排序算法)