这里改进的冒泡算法并不只是用一个标记记录有没有数据进行交换,也不只是用前置标记来记录前面不需要比较的数列的下标,而且从前后两个方向进行标记,避免前面有序和后面有序的比较,从而提高速度。
冒泡算法的改进思想:
1.记录从第0下标开始一直递增的最后一个数的下标start,在以后的每趟排序中都是从start下标开始比较,免去了从头到此下标的比较
2.记录从最后一个下标开始一直递减的最后一个下标end,在以后的每趟排序中只要判断a[end-1]和a[end],如果a[end]大,则后面的就不需要比较和交换
3.数组的长度n在每趟排序后都会n--;
4.同时当end<start时表明数组中没有可以交换的元素了,则排序完成
其实改进的冒泡算法并不能缩短很长的时间,在特大的数组长度时才会有所体现,但是在数组长度太大就不会用冒泡排序了,对于n特别大的时候,用户是容忍不了时间复杂度为o(n^2)的排序算法的
实现代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <time.h>
/*******************************************
*改进的冒泡算法
*******************************************/
void main()
{
int n; //数组的长度
int start = 0; //前置标记
printf("请输入数组的长度:\n");
scanf("%d",&n);
int *a = (int *)malloc(n*sizeof(int));
//对数组进行初始化操作
int count=n-1; //记录循环的趟数
int end = n-1; //后置标记
srand(time(0));
for(int i=0; i<n; i++)
{
a[i] = rand()%n;
}
//输出排序前的数组序列
printf("\n");
printf("排序前的数组序列:\n");
for(i=0; i<n; i++)
{
printf("%d\t",a[i]);
}
//先找到前置标记
i = 0;
while(a[i]<=a[i+1] )
{
i++;
}
start = i;
i=n-1;
while(a[i-1]<=a[i])
{
i--;
}
end = i;
//输出前置标记
printf("\n");
printf("前置标记为%d\n",start);
printf("后置标记为%d\n",end);
//排序
while(start < end){
for(i=start; i<end-1; i++)
{
if(a[i] > a[i+1] && i+1<end)
{
int temp = a[i];
a[i] = a[i+1];
a[i+1] = temp;
}
}
for(;i<count; i++)
{
if(a[i] > a[i+1])
{
int temp = a[i];
a[i] = a[i+1];
a[i+1] = temp;
}
}
//对前置标记进行修改
if(a[start-1] > a[start] && start>0)
{
start--;
if(start <0)
{
start = 0;
}
}
else
{
while(a[start]<=a[start+1] && start<end)
{
start++;
}
}
//对后置标记进行修改
count--;
while(a[end-1]<=a[end] && end>=start)
{
end--;
if(end > count)
{
end = count;
}
}
//count--;
}
//输出排序后的数组序列
printf("\n");
printf("排序后的数组序列:\n");
for(i=0; i<n; i++)
{
printf("%d\t",a[i]);
}
free(a);
}