那些时间复杂度为O(N^2)的排序
一、冒泡排序(以下默认升序从小到大)
冒泡排序作为最经典的排序教学案例,其核心思想是,把数组中最大的数放到最后一个位置,再把第二大的数放到倒数第二,以此类推。像水中的气泡往上浮的样子。
void BubbleSort(int* a, int n)//通过遍历,第一次将最大的数放到最后,第二次将第二大数放到倒数第二个位置,依次
{
int flag = 0;
for (int i = 0; i < n - 1; i++)
{
flag = 0;
for (int j = 0; j < n - 1 - i; j++)
{
if (a[j] > a[j + 1])
{
int tmp = a[j];
a[j] = a[j + 1];
a[j + 1] = tmp;
flag = 1;
}
}
if (flag == 0)//改进:flag用于判断是否发生交换,如果这一趟没有发生交换,就说明数组有序
break;
}
}
二、插入排序(On方排序里的守门员)
核心思想是,从第二个数开始,与前面的数一次比较,比他小就交换,直到第一个数;比他大就停下来,这样直到最后一个数。从这里可以看出来插入排序优于冒泡,如以下场景
int a[]={1,2,3,4,5,7,6};
对于最后一个数,插排只用交换一次即可,冒泡交换后还需遍历一遍。
void InsertSort(int* a, int n)
{
for (int i = 1; i < n; i++)
{
int end = i - 1;
int tmp = a[i];
while (end >= 0)
{
if (a[end] > tmp)
{
a[end + 1] = a[end];
end--;
}
else
{
break;
}
}
a[end + 1] = tmp;
}
}
三、选择排序
这个排序很尴尬,没冒泡经典,没插排牛逼。
核心思想是,选出来最小的数,放到左边。
void SelectSort(int* a, int n)
{//以下两个版本均可
/*int begin = 0;
while (begin < n)
{
int end = begin;
int min = end;
while (end < n)
{
if (a[end] < a[min])
{
min = end;
}
end++;
}
Swap(&a[min], &a[begin]);
begin++;
}*/
int begin = 0, end = n - 1;
while (begin < end)
{
int maxi = begin, mini = begin;
for (int i = begin; i <= end; i++)
{
if (a[i] > a[maxi])
maxi = i;
if (a[i] < a[mini])
mini = i;
}
Swap(&a[begin], &a[mini]);
if (maxi == begin)//细节,自己悟
{
maxi = mini;
}
Swap(&a[end], &a[maxi]);
++begin;
--end;
}
}
以上是三道开胃小菜,各位且尝。
ps:好久没写博客哩,最近打算拾起来,诸位助我一臂之力!