冒泡排序 深度优化
朴素冒泡
1 #include<stdio.h> 2 int main(){ 3 int n[]={0,-1,2,999,317,-5}; 4 int t; 5 for(int i=0;i<6;i++){ 6 for(int j=0;j<6;j++){ 7 if(n[j]>n[j+1]){ 8 t=n[j]; 9 n[j]=n[j+1]; 10 n[j+1]=t; 11 } 12 } 13 } 14 for(int i=0;i<6;i++) printf("%d ",n[i]); 15 return 0; 16 }
通过分析代码,我们会发现,对于每一趟排序
末尾必定是整个序列中最大的数字,他的位置已经固定了。
因此,可以将内层循环做一个优化,
设置一个w变量,使待排序序列的有效长度减少。
1 #include<stdio.h> 2 int main(){ 3 int n[]={0,-1,2,999,317,-5}; 4 int t; 5 int w=6; 6 for(int i=0;i<6;i++){ 7 for(int j=0;j<w;j++){ 8 if(n[j]>n[j+1]){ 9 t=n[j]; 10 n[j]=n[j+1]; 11 n[j+1]=t; 12 } 13 } 14 w--; 15 } 16 for(int i=0;i<6;i++) printf("%d ",n[i]); 17 return 0; 18 }
这是单侧优化,那么我们很容易就可以想到双侧优化
1 #include<stdio.h>//Orz,还能优化吗? 2 int main(){ 3 int n[10]={0,9,1,-1,-2}; 4 // for(int i=0;i<10;i++) scanf("%d",&n[i]); 5 int left=0,right=5; 6 int t; 7 while(left<right){//双向排序,当left与right相遇时,说明序列有序。 8 for(int i=left;i<right;i++){ 9 if(n[i]>n[i+1]){ 10 t=n[i]; 11 n[i]=n[i+1]; 12 n[i+1]=t; 13 } 14 } 15 right--;//每次从左走一趟,末尾必定为此序列的最大值,下一次不用排序 16 for(int i=right;i>left;i--){ 17 if(n[i]<n[i-1]){ 18 t=n[i]; 19 n[i]=n[i-1]; 20 n[i-1]=t; 21 } 22 } 23 left++;//同理,从右向左走,末尾也一定是最小值,下一次不用排序 24 } 25 for(int i=0;i<10;i++) printf("%d ",n[i]); 26 }