交换排
基本思想:两两比较待排序元素的关键字,发现两个元素的次序相反时即进行交换,知道没有反序的元素为止。本节介绍两种交换排序,即冒泡排序和快速排序。
冒泡排序:每次只能和相邻的位置数进行交换,效率低
#include<stdio.h>
int a[100];
void quickSort(int left,int right);//假设按照递增输出
void maopaoSort(int a[100],int n);
int main(){
int number,i;
scanf("%d",&number);
for(i=0;i<number;i++)
scanf("%d",&a[i]);
maopaoSort(a,number);
for(i=0;i<number;i++){
printf("%d ",a[i]);//打印出排序好的数组
}
return 0;
}
void maopaoSort(int a[100],int n){
int i,j,temp;
bool over;
for(i=0;i<n;i++){ //共需要n-1趟的比较
over=false; //每一趟开始,置over为false
for(j=0;j<n-1-i;j++){ //为什么是n-i-1呢,因为每经过一趟比较,冒泡比较的次数就少一次,一共为n-1次比较,当j=n-2时,j+1就为n-1
if(a[j+1]<a[j]){
temp=a[j];
a[j]=a[j+1];
a[j+1]=temp; //交换两个数
over=true; //如果交换了数字,说明排序还没完成
}
}
if(!over){
return ; //若某一躺执行过程中,没有发生数字的交换,说明全部已经排好序了,直接返回即可
}
}
}
快速排序:基本思想是先选择一个基准数,一般为数组的第一个数,然后我们可以假设有两个哨兵i和j,i在数组最左边,j在数组最右边,哨兵j往左边一步步移动,知道比基准数小的数组那里停下来。哨兵j往右边移动,知道在比基准数大的数组那里停下来。然后交换两个数的位置,。当哨兵i和j相遇时,就和基准数交换。这时,基准数左边的数都小于它,基准数右边的数都大于它.
图示:假设待排序的数为{6,8,2,7,9},按照从小到大的顺序输出
代码环节:
#include<stdio.h>
int a[100];
void quickSort(int left,int right);//假设按照递增输出
int main(){
int number,i;
scanf("%d",&number);
for(i=0;i<number;i++)
scanf("%d",&a[i]);
//quickSort(0,number-1); //快速排序算法
maopaoSort(a,number);
for(i=0;i<number;i++){
printf("%d ",a[i]);//打印出排序好的数组
}
return 0;
}
void quickSort(int left,int right){
int i,j,temp,m;
i=left,j=right;
if(left>right)
return ; //递归出口,即当right为-1时,返回
temp=a[left];
while(i<j){
while(a[j]>=temp&&i<j){
j--;
} //基准数在左边,就应该先从右边开始移动(因为)
while(a[i]<=temp&&i<j){
i++;
}
if(i<j){
m=a[j];
a[j]=a[i];
a[i]=m;
}
}
a[left]=a[j]; //到了这里i就等于j了,直接和基准数交换即可
a[j]=temp;
quickSort(left,i-1); //继续处理左边的,这是一个递归的过程
quickSort(i+1,right); //继续处理右边的,这是一个递归的过程
}
疑惑解决:基准数选左边就应该从右边先移动,基准数选右边就应该从左边先移动。为什么?
解答:假设我们排序的数为{6,1,2,7,9},那么基准数为6,哨兵i先移动,停在了7这个位置,然后哨兵j开始移动,和i在7的这个位置相遇了,然后7和6交换,变成了{7,1,2,6,9},这个时候有一个问题,基准数左边的7比6大了。问题就在与当i先移动时,会停在比基准数大的位置。