直接插入排序
基本思想
将一个需要排序的区间分为两个区间,一个有序区间,一个无序区间,将无序区间的数依次插入有序区间中,直到无序区间没有数字。
图解假如是升序
时间和空间复杂度
最好情况是已经有序,那么就是O(n)
最坏的情况就是此为降序,那么就是O(n^2)
但时间复杂度我们一般都说是最坏情况,那么就是O(n^2)
空间复杂度 O(1)
稳定性
稳定的
代码实现
#include<iostream>
using namespace std;
//直接插入排序 稳定的排序 时间复杂度O(n^2) 空间复杂度O(1)
//适用场景:数据量比较小,接近有序
void Insertsort(int* array,int sz)
{
for (int i = 1; i < sz; i++)
{
int key = array[i];
int end = i - 1;
//找待插入的位置 O(n)
while (end >= 0 && key < array[end])
{
array[end + 1] = array[end];
--end;
}
//插入数据
array[end + 1] = key;
}
}
int main()
{
int arr[] = { 1,5,2,6,9,7,4,3,10 };
int size = sizeof(arr) / sizeof(int);
Insertsort(arr, size);
for (int i = 0; i < size; i++)
{
printf("%d", arr[i]);
}
system("pause");
return 0;
}
希尔排序
基本思想
从本质上来讲,希尔排序实际上是对直接插入排序的一种优化,为了防止以上直接插入排序出现最坏情况影响算法效率,希尔排序对其进行了改进,在对数据进行直接排序之前,先对数据进行预排序,使之接近有序,然后再利用直接插入排序对数据进行快速排序。
先将整个待排元素序列分割成若干个子序列(由相隔某个“增量”的元素组成的)分别进行直接插入排序,然后依次缩减增量再进行排序,待整个序列中的元素基本有序(增量足够小)时,再对全体元素进行一次直接插入排序。
图解
时间和空间复杂度
分析类似上述直接插入排序,O(N)<希尔排序的时间复杂度<O(N^2),
希尔排序,当N大时,平均的时间复杂度,大约在N^1.25 – 1.6N^1.25之间。
希尔排序的空间复杂度为O(1)。
稳定性
由于多次插入排序,我们知道一次插入排序是稳定的,不会改变相同元素的相对顺序,但在不同的插入排序过程中,相同的元素可能在各自的插入排序中移动,最后其稳定性就会被打乱,所以shell排序是不稳定的。
代码实现
#include<iostream>
using namespace std
void Shellsort(int* array, int sz)
{
int gap = sz; // 10 4 2 1
//while (gap != gap / 3 + 1)
while(gap > 1)
{
gap = gap / 3 + 1;
for (int i = gap; i < sz; i++)
{
int key = array[i];
int end = i - gap;
//找待插入的位置 O(n)
while (end >= 0 && key < array[end])
{
array[end + gap] = array[end];
end -= gap;
}
//插入数据
array[end + gap] = key;
}
}
}
int main()
{
int arr[] = { 1,5,2,6,9,7,4,3,10 };
int size = sizeof(arr) / sizeof(int);
Shellsort(arr, size);
/*for (int i = 0; i < size; i++)
{
printf("%d ", arr[i]);
}*/
for (auto i : arr)
cout << i << endl;
printf("\n");
system("pause");
return 0;
}