在数据结构中讲解了7中排序算法,冒泡、选择、插入、希尔、堆排序、归并、快速排序。希尔排序感觉有点神,还没搞明白,以后再说。
本篇讲述冒泡、选择、插入这3种时间复杂度O(n^2)的算法
冒泡排序
冒泡排序非常简单,但是如果正常写的话还是有优化的余地的,一般我们写的代码为:
void BubbleSort_1(double *a,int low,int high)
{
if (!a||high<low)
return;
int i,j;
for (i=low;i<=high-1;i++)
{
for (j=i+1;j<=high;j++)
{
if (a[i]>a[j])
swap(&a[i],&a[j]);
}
}
}
但是这种方法后面部分(i后面的数组)的数值顺序是不变的,如果按照正宗的“冒泡”来的话,每一次 i 循环后,较小的数都会相应的向前靠拢,代码修改为:
void BubbleSort_2(double *a,int low,int high)
{
if (!a||high<low)
return;
int i,j;
for (i=low;i<=high-1;i++)
{
for (j=high-1;j>=i;j--)
{
if (a[j]>a[j+1])
swap(&a[j],&a[j+1]);
}
}
}
还有一种,如果某次循环后数组后面已经是顺序的话,那就不需要在进行排序了,加入一个标志位即可:
void BubbleSort_3(double *a,int low,int high)
{
if (!a||high<low)
return;
int i,j;
bool sign=true;
for (i=low ; i<=high-1&&sign ; i++)
{
sign=false;
for (j=j=high-1 ; j>=i ; j--)
{
if (a[j]>a[j+1])
{
swap(&a[j],&a[j+1]);
sign=true;
}
}
}
}
选择排序
这个就比较简单了,从首位开始,每次都选择当前位和后面数组中最小的来交换当前位。
void SelectSort(double* a,int low,int high)
{
if (!a||high<low)
return;
int i,j,min;
for (i=low;i<=high;i++)
{
min=i;
for (j=i+1;j<=high;j++)
{
if (a[j]<a[min])
min=j;
}
swap(&a[i],&a[min]);
}
}
插入排序
插入排序的算法也很简单,就是假设当前位之前的数组已经排序好,然后把当前位插入到前面数组的合适位置,具体做法为依次比较,直到找到比当前位小的值。
void InsertSort(double* a,int low,int high)
{
if (!a||high<low)
return;
int i,j;
double key;
for (i=low ; i<high ; i++)
{
j=i;
key=a[i+1];
while (a[j]>key&&j>=low)
{
a[j+1]=a[j];
j--;
}
a[j+1]=key;
}
}
可以粗略估计下这3个排序的优劣,冒泡和选择排序的比较次数都是相同的,都是O(n^2),但是选择排序的交换操作比冒泡少,所以选择要比冒泡强。而插入排序在最坏情况下的比较次数和选择排序是一样的,但是如果数组已经基本有序的话,那么内循环的执行次数是比较少的,
所以平均情况下,插入排序 优于 选择排序 优于 冒泡排序
现在我们来测试下这3种方法的时间,测试数组大小为5万,里面的值是随机生成的浮点值。(结果冒泡中第一种时间最短,好纠结啊)