vlambda博客
学习文章列表

[c语言]总结冒泡排序的一些细节

[c语言]总结冒泡排序的一些细节

1.求解前须知

对于一组乱序的数字,c语言的通常解决方法有两种,冒泡排序和选择排序。本文先介绍冒泡排序。

2.冒泡排序

①名词解释:

土豆哥自己的理解该过程就像水煮沸的逆过程一样,先是大的气泡生成(代表大数),与下面小的气泡(代表较小数)进行比较,比小的气泡数值大,就往下掉落(即交换两个数的值),直到大的气泡沉入杯底,这个过程就是执行了一轮冒泡排序,但是要让每一个较大的数字都沉入相应的位置,就要进行多次上述的过程。这样就是完整的冒泡排序。

②代码部分与理解

 for(i=0;i<n-1;i++)
     for(j=0;j<n-1-i;j++)
         if(a[j]>a[j+1])
        {
             temp = a[j];
             a[j] = a[j+1];
             a[j+1] = temp;
        }

对于关键代码部分,我们知道一共有n个数进行排序,就要进行n-1轮比较。所以外循环控制总比较轮数

同理,假设第一轮有j个数,这一轮就要与n-1个数比较,那么第二轮就要与n减1再减1个数比较(n-2),因为第一轮已经沉入底的大数不需要比较,第三轮就是n-3,第四轮就是n-4,所以可得:

在每一轮比较完成后,下一轮比较都会比上一轮减少一个,那么第i轮比较就会比上一轮减少i个,i就是外循环的轮次。

内循环控制控制每一次比较个数,然后if判断语句负责将大数往后放,即交换两个数的值。

③冒泡排序的优化。

在一个无序的数组中,冒泡排序最理想的状况是比较一轮,就是把最大的数字放入最后面就实现了有序排放,,此时要比较6回。时间复杂度为O(n)。

比较最多的情况就是每一轮都要把最大数放入到后面,也就类似于一个倒序数组,7,6,5,4,3,2,1。此时要比较

n(n-1)/2,即21回。时间复杂度为O(n²)

那么如果比较数中有相同或者实行一次冒泡排序后,数值没有变化,那么不就浪费了一轮比较了吗?为了防止出现此类情况,我们可以有加入一个标记flag,来完成上述浪费,即现在循环前加入flag=0,如果这一轮排序了就令flag为1,否则flag为0,即这一回合没排序,跳出循环。

 for (i = 0; i < n - 1; i++)//确定排序总共的轮数
 {
  int flag = 0;
  for (j = 0; j < n - 1 - i; j++)//确定每轮比较的此数
  {
  if (a[j]>a[j + 1])
  {
  //交换数值
  temp = a[j];
  a[j] = a[j + 1];
  a[j + 1] = temp;
  flag = 1;//加入标记
  }
  }
  printf("排序了第%d轮",i+1);
  if (!flag)
  break;//如果没有交换过元素,则已经有序
 }

3.完整代码

①未优化的正常冒泡排序

 #include<stdio.h>
 int main()
 {
   int i,j,temp,a[666],n;
   printf("输入需要排序的个数:\n");
   scanf("%d",&n);
   printf("输入需排序的%d个数字\n",n);
   for(i=0;i<n;i++)
   scanf("%d/t",&a[i]);
   printf("`````````````````````````\n");
   printf("显示未排序数字:\n");
   for(i=0;i<n;i++)
   printf("%4d",a[i]);
   printf("\n");
  for (i = 0; i < n - 1; i++)//确定排序趟数
 {
  for (j = 0; j < n - 1 - i; j++)//确定每轮比较次数
  {
  if (a[j]>a[j + 1])
  {
  //交换
  temp = a[j];
  a[j] = a[j + 1];
  a[j + 1] = temp;
  }
  }
 }
  printf("显示排序完成后的数字:\n");
  for(i=0;i<n;i++)
  printf("%4d",a[i]);
  printf("\n");
     return 0;
 }

优化后的排序

 #include<stdio.h>
 int main()
 {
   int i,j,temp,a[666],n;
   printf("输入需要排序的个数:\n");
   scanf("%d",&n);
   printf("输入需排序的%d个数字\n",n);
   for(i=0;i<n;i++)
   scanf("%d/t",&a[i]);
   printf("`````````````````````````\n");
   printf("显示未排序数字:\n");
   for(i=0;i<n;i++)
   printf("%4d",a[i]);
   printf("\n");
  for (i = 0; i < n - 1; i++)//确定排序趟数
 {
  int flag = 0;
  for (j = 0; j < n - 1 - i; j++)//确定每轮比较次数
  {
  if (a[j]>a[j + 1])
  {
  //交换
  temp = a[j];
  a[j] = a[j + 1];
  a[j + 1] = temp;
  flag=1;
  }
  }
  printf("显示%d轮排序后的结果:\n",i+1);
     for(j=0;j<n;j++)
  printf("%4d",a[j]);
  printf("\n");
  if(flag==0)
  break;
 }
  printf("显示排序完成后的数字:\n");
  for(i=0;i<n;i++)
  printf("%4d",a[i]);
  printf("\n");
     return 0;
 }