内部排序法——冒泡排序法

冒泡排序法又称为交换排序法,是由观察水中冒泡的变化启发而来。冒泡排序是由第一个元素开始,比较相邻元素大小,若大小顺序有误,则对调后再进行下一个元素的比较。如此扫描过一次之后就可确保最后一个元素是位于正确的顺序。接着再逐步进行第二次扫描,直到完成所有元素的排序关系为止。

      例如:数组:6、4、9、8、3、5  数组长度len=6

       原始值:6、4、9、8、3、5

       第一次扫描过程:首先比较6和4,6>4 交换顺序:4、6、9、8、3、5,接着继续比较6和9,6<9不用交换顺序保持原顺序:4、6、9、8、3、5,然后再比较9和8,9>8交换顺序:4、6、8、9、3、5,然后比较9和3,9>3交换序:4、6、8、3、9、5,最后比较9和5,9>5 交换顺序:4、6、8、3、59

       因此第一次扫描的结果为:4、6、8、3、59 总比较次数len-1=5次

       第二次扫描过程:第二次扫描从头开始,但因最后一个元素是整个数组中值最大的,所以第二次扫描只需比较到倒数第二个元素即可。

      首先比较4和6,4<6 保持顺序不变,为:4、6、8、3、59;然后比较6和8,6<8顺序不变,仍为:4、6、8、3、59 然后接着比较8和3,8>3交换顺序为:4、6、3、8、59,最后比较8和5,8>5交换顺序为:4、6、3、58、9;

      因此第二次扫描的结果为:4、6、3、58、9;   总比较次数len-2=4次

      第三次扫描过程:第三次扫描从头开始,但因最后两个元素是已排好序,所以第三次扫描只需比较到倒数第三个元素即可。

     首先比较4和6,4<6 保持顺序不变,为:4、6、3、5、8、9;然后比较6和3,6>3交换顺序:4、3、6、5、8、9

接着比较6和5,6>5交换顺序:4、3、5、6、8、9;最后比较6和8,6<8顺序不变:4、3、5、6、8、9;

      因此第三次扫描的结果为:4、3、5、6、8、9;总比较次数len-3=3次

      第四次扫描过程:第四次扫描从头开始,但因最后三个元素是已排好序,所以第四次扫描只需比较到倒数第四个元素即可。

      首先比较4和3,4>3交换顺序:3、4、5、6、8、9;最后比较4和5,4<5顺序不变:3、4、5、6、8、9

       因此第四次扫描的结果为:3、4、5、6、8、9  总比较次数len-4=2次

      第五次扫描过程:第五次扫描仍从头开始,但是最后4个元素已排好序,所以第四次扫描只需比较到倒数第五个元素即可。

       比较3和4,顺序不变:3、4、5、6、8、9   总比较次数len-5=1次

      经过5次扫描就把长度为6的数组完成了所有排序;

从以上整个过程可以发现冒泡排序具有以下性质:

1、最坏情况和平均情况均需比较(n-1)+(n-2)+……+2+1=(n-1)*n/2次;

2、时间复杂度为O(n^2),最好情况只需扫描一次,发现没有交换的动作即表示已经排好序,所以只需比较n-1次,时间复杂度为O(n);

3、由于冒泡排序只需涉及到相邻两元素之间的比较与交换,不会影响其他元素的顺序,所以是稳定的。

4、只需一个额外的空间,所以空间复杂度为O(1),空间复杂度最佳。

5、这种排序法适用于数据量小或有部分数据已经排过序的数组。

传统冒泡排序法程序实现:

/*
[名称]:传统冒泡排序法
*/

#include<stdio.h>
void maopao(int a[],int len);
void swap(int &,int &);
int main()
{
int a[6]={6,5,9,7,2,8};
int len=6;
printf("原数组数据为:");
for(int i=0;i<6;i++)
printf("%d ",a[i]);
printf("\n");
maopao(a,len);
printf("原数组排序后为:");
for(int i=0;i<6;i++)
printf("%d ",a[i]);
printf("\n");
getchar();
return 0;
}


void maopao(int a[],int _len)
{
while(--_len)
{
for(int i=0;i<_len;i++)
{
if(a[i]>a[i+1])
swap(a[i],a[i+1]);
}

printf("第%d次排序后的结果:",6-_len);
for(int i=0;i<6;i++)
printf("%d ",a[i]);
printf("\n");
}
}
void swap(int &x,int &y)
{
x=x+y;
y=x-y;
x=x-y;
}

输出结果:



传统冒泡排序有个明显的缺点,即不管数据是否已排序完成都固定执行n*(n-1)/2次,可以通过在程序中加入一个判断语句来判断何时终止程序。

/*
[名称]:改良冒泡排序法
*/
#include<stdio.h>
void bubble(int a[],int len);
void swap(int &,int &);
int main()
{
int a[6]={6,5,9,7,2,8};
int len=6;
printf("原数组数据为:");
for(int i=0;i<6;i++)
printf("%d ",a[i]);
printf("\n");
bubble(a,len);
printf("原数组排序后为:");
for(int i=0;i<6;i++)
printf("%d ",a[i]);
printf("\n");
getchar();
return 0;
}
void bubble(int a[],int _len)
{
while(--_len)
{
int flag=0;         //flag用来判断是否执行交换的动作
for(int i=0;i<_len;i++)
{
if(a[i]>a[i+1])
{
swap(a[i],a[i+1]);
flag++; //如果执行过交换,则flag不为0
}
}
if(flag==0)
break;
printf("第%d次排序后的结果:",6-_len);
for(int i=0;i<6;i++)
printf("%d ",a[i]);
printf("\n");
}

}
void swap(int &x,int &y)
{
x=x+y;
y=x-y;
x=x-y;
}

输出结果为:



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值