问题引入
先看看实现冒泡排序的代码部分:
//借助宏定义实现元素交换,可以修改为函数
#define SWAP(x,y) {int t; t = x; x = y; y = t;}
//循环体
for(i = 0; i < MAX-1 && flag == 1; i++){
flag = 0;//状态标志
for(j = 0; j < MAX-i-1; j++){
if(number[j+1] < number[j]){
//交换元素值
SWAP(number[j+1], number[j]);
flag = 1;//状态标志
}
}
}
可以看出,在冒泡排序法的基础上使用了标志状态判断这一方式,以此改进冒泡排序的速度。
问题分析
在上述情况下的冒泡排序法的交换动作不会一直进行到最后一个才结束,而是进行到 MAX-1-i 就会结束,右边排序好的元素会一直增加,使得左边排序的次数逐渐减少。
例如:
排序前:95 27 90 49 80 58 6 9 18 50
第1步:27 90 49 80 58 6 9 18 50 [95] 95浮出
第2步:27 49 80 58 6 9 18 50 [90 95] 90浮出
第3步:27 49 58 6 9 18 50 [80 90 95] 80浮出
第4步:27 49 6 9 18 50 [58 80 90 95] 58浮出
第5步:27 6 9 18 49 [50 58 80 90 95] 50浮出
第6步:6 9 18 27 [49 50 58 80 90 95] 49浮出
第7步:6 9 18 [27 49 50 58 80 90 95] 排序结束
方括号内的元素表示已排序完成。Shaker排序使用了这个概念,如果让左边的元素也具有这样的性质,让左右两边的元素都能先排序完成,如此未排序的元素会集中在中间,由于左右两边同时排序,中间未排序的部份将会很快的减少。
问题的关键就在于如何实现 双向进行 排序。先从左向右进行,再从右向左进行,完成一次排序的动作,使用left、right两个标志记录左右两端已排序的元素位置。
例如:
排序前:45 19 77 81 13 28 18 19 77 11
往右排序:19 45 77 13 28 18 19 77 11 [81]
向左排序:[11] 19 45 77 13 28 18 19 77 [81]
往右排序:[11] 19 45 13 28 18 19 [77 77 81]
向左排序:[11 13] 19 45 18 28 19 [77 77 81]
往右排序:[11 13] 19 18 28 19 [45 77 77 81]
向左排序:[11 13 18] 19 19 28 [45 77 77 81]
往右排序:[11 13 18] 19 19 [28 45 77 77 81]
向左排序:[11 13 18 19 19] [28 45 77 77 81]
括号中元素表示左右两边已排序完成,若left > right,则排序结束。
代码实现
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define MAX 10
#define SWAP(x,y) {int t; t = x; x = y; y = t;} //借助宏定义实现元素交换,可以修改为函数
#include<iostream>
using namespace std;
void bubsort(int number[]){
int i, j, k, flag = 1;
for(i = 0; i < MAX-1 && flag == 1; i++){
flag = 0;
for(j = 0; j < MAX-i-1; j++){
if(number[j+1] < number[j]){
//此处可以将SWAP宏定义中的交换修改为元素在内部交换
SWAP(number[j+1], number[j]);
flag = 1;
}
}
cout<<"第 "<<i+1<<" 次排序:";
for(k = 0; k < MAX; k++){
cout<<number[k]<<' ';
}
cout<<endl;
}
}
int main(){
int number[MAX] = {0};
int i;
srand(time(NULL)); //刷新每次产生的随机数,若无此句,每次随机数相同,亲自尝试一下便知
cout<<"\n冒泡排序:\n\n";
cout<<"排序前:";
for(i = 0; i < MAX; i++){
number[i] = rand() % 100; //产生0-99的随机数,这里没有采用固定的数组值进行排序,随机生成
cout<<number[i]<<' ';
}
cout<<endl<<endl;
bubsort(number);
return 0;
}