冒泡排序及其四种优化方式
一、冒泡排序一版
- 代码使用双循环来进行排序。
- 外部循环控制所有的回合,内部循环代表每一轮的交换处理。
- 先进行元素比较,再进行元素交换
void BubbleSort(int a[],int n){
for(int i=1;i<n;i++){
for(int j=0;j<n-i;j++){
if(a[j]>a[j+1]){
int t=a[j];a[j]=a[j+1];a[j+1]=t;
}
}
}
}
二、冒泡排序二版
- 在循环过程中若判断出数列已经有序,做出标记,可提早结束循环
- 在一版的基础上:
void BubbleSort(int a[],int n){
for(int i=1;i<n;i++){
bool isSorted=1;
for(int j=0;j<n-i;j++){
if(a[j]>a[j+1]){
int t=a[j];a[j]=a[j+1];a[j+1]=t;
isSorted=0;
}
}
if(isSorted)break;
}
}
三、冒泡排序三版
- 考察排序过程中数列有序与无序区域的边界,即有可能缩小比较次数变量的范围(j∈[0,n-i])
- 在二版的基础上:
void BubbleSort(int a[],int n){
int lastIndex=0;
int border=n-1;//初始的比较变量的范围
for(int i=1;i<n;i++){
bool isSorted=1;
for(int j=0;j<border/*仅需要比较的范围*/;j++){
if(a[j]>a[j+1]){
int t=a[j];a[j]=a[j+1];a[j+1]=t;
isSorted=0;
lastIndex=j;//记录(最后后)一次交换的位置
}
}
border=lastIndex;//更新无序区域(j)的范围上限
if(isSorted)break;
}
}
四、冒泡排序四版
- 由(每一轮从都是从左到右比较元素,进行单向的位置交换)改进为(双向的元素比较和交换)
- 外层的循环变量(i)控制排序的回合,大循环内包含两个小循环(j)
- 第一个循环从左向右比较并交换元素
- 第二个循环从右向左比较并交换元素
- 在二版的基础上:
void BubbleSort(int a[],int n){
for(int i=0;i<n/2;i++){
bool isSorted=1;
for(int j=i;j<n-i-1;j++){//奇数轮次从左到右
if(a[j]>a[j+1]){
int t=a[j];a[j]=a[j+1];a[j+1]=t;
isSorted=0;
}
}
if(isSorted)break;
isSorted=1;//重新标记
for(int j=n-i-1;j>i;j--){//偶数轮次从右到左
if(a[j-1]>a[j]){
int t=a[j];a[j]=a[j-1];a[j-1]=t;
isSorted=0;
}
}
if(isSorted)break;
}
}
五、冒泡排序五版
- 对于双向的冒泡排序,需要设置两个边界点
- 在三版的基础上:
void BubbleSort(int a[],int n){
int L_lastIndex=0,R_lastIndex=0;//记录一侧最后一次的交换位置
int L_border=0,R_border=n-1;//边界点的初始化
for(int i=0;i<n/2;i++){
bool isSorted=1;
for(int j=L_border;j<R_border;j++){
if(a[j]>a[j+1]){
int t=a[j];a[j]=a[j+1];a[j+1]=t;
isSorted=0;
R_lastIndex=j;//记录(最后)一次交换位置
}
}
R_border=R_lastIndex;//更新从左到右循环的右边界
if(isSorted)break;
isSorted=1;
for(int j=R_border;j>L_border;j--){
if(a[j-1]>a[j]){
int t=a[j];a[j]=a[j-1];a[j-1]=t;
isSorted=0;
L_lastIndex=j;//记录(最后)一次交换位置
}
}
L_border=L_lastIndex;//更新从右到左循环的左边界
if(isSorted)break;
}
}