BubbleSort
冒泡排序是许多人接触的第一种排序方式,由于这种方式比较简单,所以大部分人也没有深入研究,所以写出的代码是这样的:
void BubbleSort(int *arr, int len)
{
assert(arr);
int i = 0;
int j = 0;
int tmp = 0;
for (i = 0; i < len - 1; i++)
{
for (j = 0; j < len -i- 1; j++) //每排序一趟,则必然后面有一个已经有序,可以减少循环缩小排序的范围
{
if (arr[j]>arr[j + 1])
{
tmp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = tmp;
}
}
}
}
其实我想告诉你的是冒泡排序还有三种优化方式:(以下都是以升序为例)
例如要排序下面这组数据: 1 2 3 4 5 6 7 8 10 9
按照上面的排序方式,第一趟将10 与 9交换后已经就有序了,所以接下来的8趟都是多余的。这时我们可以加一个标记来判断每一趟排序时是否交换过数据,如果哪一趟排序没有交换数据,则这时就已经有序了。
void BubbleSort(int *arr, int len)
{
assert(arr);
int i = 0;
int j = 0;
int flag = 0;
int tmp = 0;
for (i = 0; i < len - 1; i++)
{
flag = 1; //flag初始时为1
for (j = 0; j < len - i - 1; j++) //每排序一趟,则必然后面有一个已经有序,可以缩小排序的范围
{
if (arr[j]>arr[j + 1]) //只要要交换数据,则flag就会被修改
{
tmp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = tmp;
flag = 0; //只要这组数还未完全有序,则一定会修改flag为0
}
}
if (flag) //如果排序一趟,发现已经有序,则不进入if,flag没被修改
{
break;
}
}
}
这样修改之后虽然提高了冒泡排序的效率,但是还是不是最理想的!!!
例如现在要排序下面这组数据:1 2 5 7 4 3 6 8 9 10
根据上面的算法我们可以写出如下代码:
void BubbleSort(int *arr, int len)
{
assert(arr);
int i = 0;
int j = 0;
int flag = 0;
int tmp = 0;
int m = 0; //用来记录最后一次交换的位置
int k = len-1;
for (i = 0; i < len - 1; i++)
{
m = 0;
flag = 1;
for (j = 0; j < k; j++) //无序区的范围只从第一个元素,到上一趟最后一次交换的位置k
{
if (arr[j]>arr[j + 1])
{
tmp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = tmp;
flag = 0; //只要这组数还未完全有序,则一定会修改flag为0
m = j;
}
}
if (flag) //如果排序一趟,发现已经有序,则不进入if,flag没被修改
{
break;
}
k = m; //将k置成最后一次交换的位置
}
}
写成上面这种方式 ,冒泡排序的效率已经得到了极大的提升,下面我们再来介绍第三种优化的方法!!!
对下面这组这组数进行排序:2 3 4 5 6 7 8 9 10 1
根据上面的算法,我们可以写出如下代码:
void BubbleSort(int *arr, int len)
{
assert(arr);
int i = 0;
int j = 0;
int flag = 0;
int m = 0; //记录最后一次交换的位置
int n = 0;
int k = len - 1;
for (i = 0; i < len - 1; i++)
{
m = 0;
flag = 1;
//正序扫描找最大值
for (j = n; j < k; j++) //无序区的范围只从第一个元素,到上一趟最后一次交换的位置k
{
if (arr[j]>arr[j + 1])
{
int tmp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = tmp;
flag = 0; //只要这组数还未完全有序,则一定会修改flag为0
m = j;
}
}
k = m;
if (flag) //如果排序一趟,发现已经有序,则不进入if,flag没被修改
{
break;
}
//反序扫描找最小值
for (j = k; j>n; j--) //无序区的范围只从第一个元素,到上一趟最后一次交换的位置k
{
if (arr[j]<arr[j - 1])
{
int tmp = arr[j];
arr[j] = arr[j - 1];
arr[j - 1] = tmp;
flag = 0; //只要这组数还未完全有序,则一定会修改flag为0
}
}
n++;
if (flag) //如果排序一趟,发现已经有序,则不进入if,flag没被修改
{
break;
} //将k置成最后一次交换的位置
}
}
这种改进之后的冒泡排序是不是很厉害!!! ^v^