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^
时间: 2025-01-08 00:05:48