传统的冒泡排序算法我们应该很熟悉,主要的原理是:
1.比较相邻的元素。如果第一个比第二个大,就交换他们两个。
2.对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。
3.针对所有的元素重复以上的步骤,除了最后一个。
4.持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。
但是此种方法每一趟循环只能找到一个最大或者最小的值,效率低,基于这个缺点,我们可以利用在每一趟排序中进行正向
和反向两遍冒泡的方法,一次可以得到两个值,最大值和最小值,确定两个值的位置这样我们的循环次数就减少了一半。
直接上代码吧:
void bubble_sort_test(){
int arr[] = { 5, 6, 8, 3, 9, 2, 7, 0, 4, 1 };
int sz = sizeof(arr)/sizeof(arr[0]);
for (int i = 0; i < sz/2; i++){
//正向循环 把最大这下沉到 j+1的位置
for (int j = i; j< sz - i - 1; j++){
//前一个数大于后一个 下沉
if (arr[j]>arr[j + 1]){
int tmp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = tmp;
}
}
//反向循环 把最小者上冒的i的位置。
for (int j = sz-1; j>i; j--){
// 后一个数比前一个数小 上冒
if (arr[j]<arr[j - 1]){
int tmp = arr[j];
arr[j] = arr[j - 1];
arr[j - 1] = tmp;
}
}
}
int i = 0;
for (i = 0; i < sz; i++){
printf("%d ", arr[i]);
}
}
int main(){
bubble_sort_test();
getchar();
return 0;
}
还有一种情况,如果给出的数组中已经有大量已经排序好的数据,那么按照原始方法我们还是要跑n-1趟,这是挺浪费时间的。
于是可以这样,我们每跑完一趟就判断一次原数组是否有序,如果有序就结束。
所以就有了一个标志位flag来助我们判断。
首先来看看分析:
话不多说,代码才是硬道理:
void bubble_sort(int arr[], int sz)
{
int i = 0;
int j = 0;
for (i = 0; i < sz - 1; i++)
{
int flag = 1;//假定每次进入都是有序的 flag为1;
for (j = 0; j < sz - i - 1; j++){
int tmp = 0;
if (arr[j] > arr[j + 1]){
tmp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = tmp;
flag = 0;//如果发生交换,则flag 置为0;
}
}
if (flag == 1)//如果这趟走完,没有发生交换,则原数组有序;
break;
}
}
如果有兴趣,可以将上下两个代码合二为一,就是最终我能想到的优化了。