直接插入排序
实现思想(升序)
直接插入排序,类似我们玩扑克牌(牌已经有序),将这个数字从后往前比较,如果这个数小于前面比较的数,被比较的这个数往后挪,直到这个数插入到合适的位置,使手中的牌保持有序。
动图演示
因为一开始数组并不是有序的,一个元素是天然有序,所以从第二个元素开始处理,变量x为要插入的元素,变量index为有序片段的最后一个元素位置,第一趟排序后,有序片段为2个元素,变量x就为数组第三个元素,插入到有序片段,重复此过程,直到最后一个元素插入。数组整体就有序了。
代码实现
void InsertSort(int* a, int n)
{
for (int i = 0; i < n - 1; i++)////n-1是数组元素个数,当i=n-2时,最后一个元素插入
{
//单趟排序
int index = i;//记录的是每一次有序数组中末尾元素的位置
int x = a[index + 1];//当index=0时,x表示数组中第二个元素
while (index >= 0)
{
if (x < a[index])
{
a[index + 1] = a[index];
index--;//继续处理前面的元素
}
else
{
break;//放到循环外处理
}
}
a[index+1] = x;
//1.插入元素比有序数组元素都小,插入到数组第一个位置
//2.处理的是break,待插入元素找到应插入位置
}}
该算法的时间复杂度为O(N^2) 空间复杂度为O(1)
如果数组本身有序或者接近有序,时间复杂度为O(N)
希尔排序
动图演示
希尔通过gap分组多次预排,使数组接近有序,然后进行一次直接插入排序,完成排序。
初始数组 9 1 2 5 7 4 8 6 3 5
1.第一次预排gap=5,将数组分成5组,每组两个元素,这里进行5组数据的插入排序。
2.第二次预排gap=2,将数组分成2组,每组5个元素,这里进行2组数据的插入排序。
3.第三次gap=1,这就是一次直接插入排序。
void ShellSort(int* a, int n)
{
int gap = n;
while (gap > 1)//gap=1时,循环结束
{
gap = gap / 2;//gap折半
for (int i = 0; i < n - gap; i++)//for循环后数组预排完成,这里是所有gap组一起处理,并不是gap组单独处理
{
int index = i;
int x = a[index + gap];
while (index >= 0)
{
if (a[index] > x)
{
a[index + gap] = a[index];
index -= gap;
}
else
{
break;
}
}
a[index + gap] = x;
}
}
}
while (gap > 1)
{
gap = gap / 2;//gap折半//这就是gap组分开处理,多套一层循环
for (int j = 0; j < gap; j++)
{
for (int i = j; i < n - gap; i += gap)//第一趟处理的就是gap分组中的第一组
{
//数据排序
}
}
}
}
时间复杂度:O ( N* l o g N ) 空间复杂度:O ( 1 )
平均时间复杂度:O ( N^1.3 )