在我们内存中我们一般会有一些没有顺序的数据,我们成为内排序,而今天分享八大排序的是时间复杂度为O(N^2)的插入排序,选择排序和教学意义比较强的冒泡排序。
插入排序?
?这是插入排序的动图,通过动图我们也是可以看到我们的插入排序的思想
从当前的位置往前找小,如果当前位置的值是比前面的位置下的,前面位置往后挪动覆盖,因为会覆盖当前的位置,所以我们需要一个key来保存我们的当前的位置,如果往前找位置的时候,这个位置的值是比我们当前位置的值小的时候,循环就开始停下来,这个时候我们退出循环,在进行插入就是插入排序,我们先来看看我们的代码,然后画图来给大家看看。
void InsertSort(int* a, int n)
{
for (int i = 0; i < n - 1; i++)
{
int end = i;
int key = a[end + 1];
while (end >= 0)
{
if (a[end] > key)
{
a[end + 1] = a[end];
end--;
}
else
{
break;
}
}
a[end + 1] = key;
}
}
代码是很简短的,我们给个数组是{9, 8, 7, 6, 5, 4, 3, 2, 1}。
end需要往前移动找小,如果比他大,那这个位置的数就得往后移动。?
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?选择排序
?
?
void Swap(int* p1, int* p2)
{
int tmp = *p1;
*p1 = *p2;
*p2 = tmp;
}
void SelectSort(int* a, int n)
{
for (int j = 0; j < n; j++)
{
int mini = j;
for (int i = j; i < n; i++)
{
if (a[i] < a[mini])
{
mini = i;
}
i++;
}
Swap(&a[mini], &a[j]);
}
}
这个就是选择排序的基础玩法,但是这个选择排序我们一次只找出最小的值,我们这里还是遍历一遍数组了,遍历一遍数组只找出一个值还是有点亏,所以我们可以优化一下,一次性找出两个值,分别是最大值和最小的值,但是!优化后还是有些缺点,就是存在覆盖问题,我们来先看看代码吧。
void SelectSort(int* a, int n)
{
int begin = 0;
int end = n - 1;
while (begin < end)
{
int mini = begin;
int maxi = begin;
for (int i = begin; i <= end; i++)
{
if (a[i] < a[mini])
{
mini = i;
}
if (a[i] > a[maxi])
{
maxi = i;
}
}
Swap(&a[begin], &a[mini]);
if (begin == maxi)
{
maxi = mini;
}
Swap(&a[end], &a[maxi]);
begin++;
end--;
}
}
优化之后判断哪个地方需要我们注意一下,因为begin的位置可能开始就是最大值,这里还需要注意的就是我们的maxi和mini一定要放到循环里面,因为你不放进去他每次都是从一开始的begin,就是下标0开始,这样会打乱我们刚开始的排序。
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?冒泡排序
冒泡排序还不简单,我们直接手搓,要是这个小编还能写错,我直接eat? big shit
void Swap(int* p1, int* p2)
{
int tmp = *p1;
*p1 = *p2;
*p2 = tmp;
}
void BubbleSort(int* a, int n)
{
for (int i = 0; i < n; i++)
{
int j = 0;
for (j = 0; j < n -1 - i; j++)
{
if (a[j] > a[j + 1])
{
Swap(&a[j], &a[j + 1]);
}
}
}
}
那我们的三个时间复杂度是O(N^2)的排序也是终于完成了。我们下次来讲讲在插入排序的基础上实现希尔排序。