一:冒泡算法
冒泡算法的名字来历,来自于较轻的气泡会上升,较重的气泡会下降这么一个物理事实。
假设有一组数。排成列。存储在数组a[10]中。
我们可以利用这个物理现象来使其按照升序或者降序排列。
从头至尾部时,我们希望把最重的或最轻的放置头部。
这时我们知道,头部是最重的。这时,我们需要从第二个位置开始往尾部遍历。使剩下数目的最重的气泡放在第二个位置。
在选取哪个最重的气泡时,我们不得不从尾部向头部的方向进行遍历。
所以嵌套for循环需要写成如下形式:
for(i=0;i<n;i--)
for(j=n-1;j>i;j++)
{
}
以上表述是将每趟比较的极值放置最前端。
每趟由后往前推
for(i=n-1;i>0;i--)
for(j=0;j<i;j++)
{
}
以上表述是将每趟比较的极值放置最后端。
每趟由前往后推
这个时候我们需要考虑在排列求最大的过程。
每次排列。从尾部n-1开始,到i结束。
又必须一次只能比较交换相邻的两个。好像是滑动窗口一样。进来一个出去一个的样子。
所以。应该由第一个与第二比。从后向前时。是a[j]与a[j-1]。从前往后时应该是a[j]与 a[j+1]
所以补全上面如下
for(i=0;i<n;i++)
for(j=n-1;j>i;j++)
{
if(a[j]>a[j-1])
{
temp=a[j];
a[j]=a[j+1];
a[j+1]=temp
}
}
以上表述是将每趟比较的极值放置最前端。
每趟由后往前推
for(i=n-1;i>0;i--)
for(j=0;j<i;j++)
{
if(a[j]>a[j+1])
{
temp=a[j];
a[j]=a[j+1];
a[j+1]=temp
}
}
以上表述是将每趟比较的极值放置最后端。
每趟由前往后推。
我想我已经讲的非常清楚了。
这是一个嵌套for循环。
但是两个for循环之间是有一定的关联关系的。
下面给出他们的实际意义。
外层和内存的方向总是相反的。外层指针指的是无序队列结束的地方。也是有序队列逐渐增大的的尾部。内层就是利用窗口,将无序队列里的最值元素移动到有序队列的尾部。所以,内层的指针会从远向有序队列的尾部靠近。
外层for循环:需要遍历比较的队列。
但是我们知道当队列中只有一个数时,是不需要进行内存for循环的。所以,外层只需囊括遍历头n-1个即可。
内层for循环:对队列逐一进行遍历计较。
同样对于内层for循环。由于是两个两个的比较着前进。所以实质上只需比较队列长度leng-1次。所以。应注意两个for循环的写法。
记住以下要点即可。
1:两个for循环只涉及到三个数。0;n-1;i
2:先写=再写 <或者>。
3:如果内层循环递增,那么,与较大的比。
反之,如果内层递减。那么,与较小的比。
#include <stdio.h>
#include <stdlib.h>
#define m 20;
int bubbles(int a[],int n);
int bubbles2(int a[],int n);
void main()
{
int i;
int a[10];
srand((unsigned int)time(0));
for (i=0;i<10;i++)
{
a[i]=rand()%m;
}
for (i=0;i<10;i++)
{
printf("before sort:%d\n",a[i]);
}
bubbles2(a,10);
for (i=0;i<10;i++)
{
printf("after sort:%d\n",a[i]);
}
}
int bubbles(int a[],int n)
{
int i,j,temp;
for (i=0;i<n-1;i++)
for (j=n-1;j>i;j--)
{
if(a[j-1]>a[j])
{
temp=a[j-1];
a[j-1]=a[j];
a[j]=temp;
}
}
}
int bubbles2(int a[],int n)
{
int i,j,temp;
for (i=n-1;i>0;i--)
for (j=0;j<i;j++)
{
if(a[j+1]>a[j])
{
temp=a[j+1];
a[j+1]=a[j];
a[j]=temp;
}
}
}
下面讨论一下对冒泡算法的改进方法:
(1):我们知道如果某趟比较遍历中,如果没有发生转换位置,那么可视为已经排序完毕。依据此条件进行改进。
设置标志位flag。若该趟有交换发生,则循序进行下一趟便利。否则停止。
程序如下:
int bubbles_inprove_flag2(int a[],int n)
{
int i,j,temp;
int flag;
int num;
num=0;
flag=1;
for (i=n-1;i>0;i--)
if(flag>0)
{
flag=0;
for (j=0;j<i;j++)
{
if(a[j+1]<a[j])
{
temp=a[j+1];
a[j+1]=a[j];
a[j]=temp;
flag=1;
}
num++;
}
}
printf("num:%d\n",num);
}
但是这并不能组织外层的遍历。只是进入内层循环时,使得由if的条件判断给阻挡住了。
再次改善后如下:
int bubbles_inprove_flag(int a[],int n)
{
int i,j,temp;
int flag;
int num;
num=0;
flag=1;
//for (i=n-1;i>0;)
i=n-1;
while(flag>0)
{
flag=0;
for (j=0;j<i;j++)
{
if(a[j+1]<a[j])
{
temp=a[j+1];
a[j+1]=a[j];
a[j]=temp;
flag=1;
}
num++;
}
i--;
}
printf("num:%d\n",num);
}
or(将flag信息融入外层判断中,即可及时阻止外层判断的继续进行)
public static int bubble(int[] Array)
{
int Length = Array.Length;
int flag = 1;
for (var i = Length - 1; flag ==1 && i > 0; i--)
{
flag=0;//clear the flag
for (var j = 0; j < i; j++)
{
if (Array[j] < Array[j + 1])
{
var temp = Array[j];
Array[j] = Array[j + 1];
Array[j + 1] = temp;
flag = 1;// set the flag
}
}
}
return 1;
}
结果如下:
#include <stdio.h>
#include <stdlib.h>
void main()
{
int a[10]={5,8,4,3,9,6,1,2,7,0};
int n;
int i;
int j;
int temp;
n=sizeof(a)/sizeof(int);
for(i=0;i<n;i++)
{
printf("%d\n",a[i]);
}
for (i=1;i<n;i++)
{
for (j=0;j<n-i;j++)
{
if (a[j]<a[j+1])
{
temp=a[j];
a[j]=a[j+1];
a[j+1]=temp;
}
}
}
for(i=0;i<n;i++)
{
printf("%d\n",a[i]);
}
}

本文详细介绍了冒泡排序算法的工作原理,包括如何使用物理现象进行排序,并通过两个嵌套循环实现升序或降序排列。文章进一步探讨了冒泡排序的改进方法,如使用标志位来优化算法效率,以及对算法进行动态终止的策略。
2870

被折叠的 条评论
为什么被折叠?



