经典排序算法 — 冒泡排序Bubble Sort
原理是相邻的数字两两进行比较,按照从小到大或者从大到小的顺序进行交换,
这样一趟过去后,最大或最小的数字被交换到了最后一位,
然后再从头开始进行两两比较交换,直到倒数第二位时结束,其余类似看例子
例子:从小到大排序,
原始待排序数组| 6 | 2 | 4 | 1 | 5 | 9 |
第一趟排序(外循环)
第一次两两比较6 > 2交换(内循环)
交换前状态| 6 | 2 | 4 | 1 | 5 | 9 |
交换后状态| 2 | 6 | 4 | 1 | 5 | 9 |
第二次两两比较,6 > 4交换
交换前状态| 2 | 6 | 4 | 1 | 5 | 9 |
交换后状态| 2 | 4 | 6 | 1 | 5 | 9 |
第三次两两比较,6 > 1交换
交换前状态| 2 | 4 | 6 | 1 | 5 | 9 |
交换后状态| 2 | 4 | 1 | 6 | 5 | 9 |
第四次两两比较,6 > 5交换
交换前状态| 2 | 4 | 1 | 6 | 5 | 9 |
交换后状态| 2 | 4 | 1 | 5 | 6 | 9 |
第五次两两比较,6 < 9不交换
交换前状态| 2 | 4 | 1 | 5 | 6 | 9 |
交换后状态| 2 | 4 | 1 | 5 | 6 | 9 |
第二趟排序(外循环)
第一次两两比较2 < 4不交换
交换前状态| 2 | 4 | 1 | 5 | 6 | 9 |
交换后状态| 2 | 4 | 1 | 5 | 6 | 9 |
第二次两两比较,4 > 1交换
交换前状态| 2 | 4 | 1 | 5 | 6 | 9 |
交换后状态| 2 | 1 | 4 | 5 | 6 | 9 |
第三次两两比较,4 < 5不交换
交换前状态| 2 | 1 | 4 | 5 | 6 | 9 |
交换后状态| 2 | 1 | 4 | 5 | 6 | 9 |
第四次两两比较,5 < 6不交换
交换前状态| 2 | 1 | 4 | 5 | 6 | 9 |
交换后状态| 2 | 1 | 4 | 5 | 6 | 9 |
第三趟排序(外循环)
第一次两两比较2 > 1交换
交换后状态| 2 | 1 | 4 | 5 | 6 | 9 |
交换后状态| 1 | 2 | 4 | 5 | 6 | 9 |
第二次两两比较,2 < 4不交换
交换后状态| 1 | 2 | 4 | 5 | 6 | 9 |
交换后状态| 1 | 2 | 4 | 5 | 6 | 9 |
第三次两两比较,4 < 5不交换
交换后状态| 1 | 2 | 4 | 5 | 6 | 9 |
交换后状态| 1 | 2 | 4 | 5 | 6 | 9 |
第四趟排序(外循环)无交换
第五趟排序(外循环)无交换
排序完毕,输出最终结果1 2 4 5 6 9
假设:n个数 外层循环 n-1 次 内层循环(每一次外层循环) n-1-i 次
C程序 从小到大
void BubbleSort(int *array, int n)
{
int i, j, temp = 0;
//外层循环
for (i=0; i<n-1; i++)
{
//内层循环
for (j=0; j<n-1-i; j++)
{
//交换两个数的位置
//不可以是arr[j] >= arr[j+1],因为冒泡排序是一个稳定的算法,加上=之后就不是一个稳定的算法了
if (array[j] > array[j+1])
{
temp = array[j];
array[j] = array[j+1];
array[j+1] = temp;
}
}
}
}
注意:上面的冒泡排序不是一个优秀的算法
试想,如果要排列的数列为 1、2、3、4、5、8、9、7、6
只需要比较4趟就可以。但是上面的算法中却比较了9次。造成效率低下。也就是说在4趟比较完之后就意味着排序就已经排好了。可以结束了。认识到这一点就可以对程序进行改进。
改进:
在算法中设置一个flag变量。当flag为1时说明本趟排序中仍有元素要交换,因此还需要下一趟的比较。当flag为0时,说明本趟排序中已经木有要交换的元素,只有元素的比较,说明已经排好序了,只比较不交换说明已经排好序。排序就结束了。
改进后的程序
void BubbleSort(int* array, int n)
{
int i, j;
bool flag = false;
for (i=0; i<n-1; i++)
{
flag = false;
for (j=0; j<n-1-i; j++)
{
//在这里引入一个新的交换两个数的方法,仅限于交换两个整数且i不能等于j
if (array[j] > array[j+1])
{
array[j] = array[j]^array[j+1];
array[j+1] = array[j]^array[j+1];
array[j] = array[j]^array[j+1];
//发生数据交换就把flag置true
flag = true;
}
}
//本趟排序未发生交换,则说明之前的都是已经有序的,则可以提前结束算法
if (!flag)
return;
}
}