插入排序
类似于摸牌
InsertSort:O(N^2)
最坏情况:逆序有序
最好情况:O(N)顺序有序
比冒泡排序实际应用更高效
以下是单趟排序,实现多趟需要再嵌套一个for循环,控制end的初值由0到n-1
void PrintArray(int* a, int n)
{
for (int i = 0; i < n; i++)
{
printf("%d ", a[i]);
}
printf("\n");
}
// 时间复杂度:O(N^2) 逆序
// 最好的情况:O(N) 顺序有序
void InsertSort(int* a, int n)
{
// [0, end] end+1
for (int i = 0; i < n - 1; ++i)
{
int end = i;
int tmp = a[end + 1];
while (end >= 0)
{
if (tmp > a[end])
{
a[end + 1] = a[end];
--end;
}
else
{
break;
}
}
a[end + 1] = tmp;
}
}
冒泡排序:
BubbleSort:O(N^2)
最好情况:O(N),包含标志位即可实现,表示第一次就没有发生交换,也就是说前一个总比后一个大,结束
先选出一个最大的,交换到最后一个位置。
第一个数进行n-1次交换,也就是小于n次交换,n-j(j=0)
第二个数进行n-2次交换,也就是小于n-1次交换,n-j(j=1)
第n个数进行n-n次交换,也就是小于n-(n-1)次交换,n-j(j=n-1)
void Swap(int* p1, int* p2)
{
int tmp = *p1;
*p1 = *p2;
*p2 = tmp;
}
void BubbleSort(int* a, int n)
{
for (int j = 0; j < n; j++)
{
bool exchange = false;
for (int i = 1; i < n - j; i++)
{
if (a[i - 1] > a[i])
{
Swap(&a[i - 1], &a[i]);
exchange = true;
}
}
if (exchange == false)
break;
}
//for (int i = 0; i < n-1; i++)
//{
// if (a[i] > a[i+1])
// {
// Swap(&a[i], &a[i+1]);
// }
//}
}
希尔排序
类似于插入排序,但是存在gap的间隔
ShellSort:平均O(N^1.3)
以上是分组排序,可以替换成多组并排
gap随着n进行变化
越到后面的每一次都可能比设想小,不能完全按逆序去算,因为前面已经排过了
最后一轮,gap=1,同时已经非常接近有序了。累计挪动大约n次
void ShellSort(int* a, int n)
{
int gap = n;
// gap > 1时是预排序,目的让他接近有序
// gap == 1是直接插入排序,目的是让他有序
while (gap > 1)
{
//gap = gap / 2;
gap = gap / 3 + 1;
//+1可以保证最后一次一定是1
for (int i = 0; i < n - gap; ++i)
{
int end = i;
int tmp = a[end + gap];
while (end >= 0)
{
if (tmp < a[end])
{
a[end + gap] = a[end];
end -= gap;
}
else
{
break;
}
}
a[end + gap] = tmp;
}
}
/*for (int j = 0; j < gap; ++j)
{
for (int i = j; i < n-gap; i += gap)
{
int end = i;
int tmp = a[end + gap];
while (end >= 0)
{
if (tmp < a[end])
{
a[end + gap] = a[end];
end -= gap;
}
else
{
break;
}
}
a[end + gap] = tmp;
}
}*/
}