冒泡排序算法的有两种方式,如下:
一、邻比法:
1. 依次比较相邻的两个数,将小数放在前面,大数放在后面。即在第一趟:首先比较第1个和第2个数,将小数放前,大数放后。然后比较第2个数和第3个数,将小数放前,大数放后,如此继续,直至比较最后两个数,将小数放前,大数放后。至此第一趟结束,将最大的数放到了最后。
2. 在第二趟:仍从第一对数开始比较(因为可能由于第2个数和第3个数的交换,使得第1个数不再小于第2个数),将小数放前,大数放后,一直比较到倒数第二个数(倒数第一的位置上已经是最大的),第二趟结束,在倒数第二的位置上得到一个新的最大数(其实在整个数列中是第二大的数)。
3. 如此下去,重复以上过程,直至最终完成排序。
二、 逐比法:
1. 从第一个元素开始与后边所有元素两两比较,接着第二元素与后边所有元素两两比较,以此类推。即在第一趟:首先比较第1个和第2个数,将小数放前,大数放后。然后比较第1个数和第3个数,将小数放前,大数放后,如此继续,直至比较最后两个数,将小数放前,大数放后。至此第一趟结束,将最小的数放到了第1位上。
2. 在第二趟:比较第2个和第3个数,将小数放前,大数放后。然后比较第2个数和第4个数,将小数放前,大数放后,如此继续,直至比较最后两个数,将小数放前,大数放后。至此第二趟结束,将第二小的数放到了第2位上。
3. 如此下去,重复以上过程,直至最终完成排序。
冒泡算法的度量如下:
数据结构 数组
最差时间复杂度 O(n^2)
最优时间复杂度 O(n)
平均时间复杂度 O(n^2)
最差空间复杂度 总共O(n),需要辅助空间O(1)
最佳算法 No
上边的两种方法,也可以从后往前进行比较,所以可以演化出4种排法,可以参见下边的源码1-4。
此四种算法可以做如下改进:
在排序过程中,执行完最后的排序后,虽然数据已全部排序完备,但程序无法判断是否完成排序,为了解决这一不足,可设置一个标志位flag,将其初始值设置为非0,表示被排序的表是一个无序的表,每一次排序开始前设置flag值为0,在进行数据交换时,修改flag为非0。在新一轮排序开始时,检查此标志,若此标志为0,表示上一次没有做过交换数据,则结束排序;否则进行排序;参见下边第5个源码
1.
j∈[0,N-1-i) //每遍循环要处理的无序部分
swap(j,j+1) //从第一个元素开始相连两两比较(升序/降序),第一遍会将最大(或者最小)的元素一步一步移到最后的位置上,第二遍会将第二大(或者第二小)的元素一步一步移到倒数第二个位置上
源码:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
void print_ary( int * ary, unsigned int len )
{
while( len-- > 0 ) {
printf("%d ", *ary++ );
}
putchar('\n');
}
void create_rondom_number(int **parray, unsigned int number)
{
struct timeval tpstart;
unsigned int i =0;
if (NULL != *parray)
{
return;
}
*parray = (int *)malloc(sizeof(unsigned int) * number);
(void)memset(*parray, 0, sizeof(unsigned int) * number);
gettimeofday(&tpstart,NULL);
//srandom(time(NULL));
srandom(tpstart.tv_usec);
for (i=0; i<number; ++i)
{
//(*parray)[i] = random()%number; // range is [0, number-1]
//(*parray)[i] = random()%(b-a) + a; //range is [a, b)
((*parray)[i] = 1 + (int) ((double)number * rand() / (RAND_MAX + 1.0))); // [1, number]
}
}
/*
* i∈[0,N-1) //从前往后循环N-2遍
* j∈[0,N-1-i) //每遍循环要处理的无序部分
* swap(j,j+1) //从第一个元素开始相连两两比较(升序/降序),
* 第一遍会将最大(或者最小)的元素一步一步移到最后的位置上,
* 第二遍会将第二大(或者第二小)的元素一步一步移到倒数第二个位置上
*/
int bubble_sort( int * ary, int len )
{
int i, j;
int temp;
for( i=0; i<len-1; ++ i ) {
printf("\n\n");
for( j=0; j<len-i-1; j++ ) {
printf("a[%d] & a[%d](i=%d, j=%d) ", j, j+1, i, j);
if( ary[j] > ary[j+1] ) {
temp = ary[j];
ary[j] = ary[j+1];
ary[j+1] = temp;
printf("swap ");
}
print_ary( ary, len );
}
}
}
int main( int argc, char ** argv )
{
int *pary = NULL;
if (argc !=2)
{
printf("\nUsage: %s Number\n", argv[0]);
return -1;
}
create_rondom_number(&pary, (unsigned int)atoi(argv[1]));
printf("\n\nrandom number: ");
print_ary( pary, (unsigned int)atoi(argv[1]) );
printf("Start sortting: \n");
bubble_sort( pary, (unsigned int)atoi(argv[1]));
printf("\n\nafter sorted: ");
print_ary( pary, (unsigned int)atoi(argv[1]) );
return 0;
}
运行结果:
[root@localhost sort]# ./bubble 5
random number: 5 5 3 2 5
Start sortting:
a[0] & a[1](i=0, j=0) 5 5 3 2 5
a[1] & a[2](i=0, j=1) swap 5 3 5 2 5
a[2] & a[3](i=0, j=2) swap 5 3 2 5 5
a[3] & a[4](i=0, j=3) 5 3 2 5 5
a[0] & a[1](i=1, j=0) swap 3 5 2 5 5
a[1] & a[2](i=1, j=1) swap 3 2 5 5 5
a[2] & a[3](i=1, j=2) 3 2 5 5 5
a[0] & a[1](i=2, j=0) swap 2 3 5 5 5
a[1] & a[2](i=2, j=1) 2 3 5 5 5
a[0] & a[1](i=3, j=0) 2 3 5 5 5
after sorted: 2 3 5 5 5
[root@localhost sort]#
2.
j∈[N-1,N-i-1) //每遍循环要处理的无序部分
swap(j,j-1) //从倒数第一个元素开始相连两两比较(升序/降序),第一遍会将最大(或者最小)的元素一步一步移到第一个位置上,第二遍会将第二大(或者第二小)的元素一步一步移到第二个位置上
源码:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
void print_ary( int * ary, unsigned int len )
{
while( len-- > 0 ) {
printf("%d ", *ary++ );
}
putchar('\n');
}
void create_rondom_number(int **parray, unsigned int number)
{
struct timeval tpstart;
unsigned int i =0;
if (NULL != *parray)
{
return;
}
*parray = (int *)malloc(sizeof(unsigned int) * number);
(void)memset(*parray, 0, sizeof(unsigned int) * number);
gettimeofday(&tpstart,NULL);
//srandom(time(NULL));
srandom(tpstart.tv_usec);
for (i=0; i<number; ++i)
{
//(*parray)[i] = random()%number; // range is [0, number-1]
//(*parray)[i] = random()%(b-a) + a; //range is [a, b)
((*parray)[i] = 1 + (int) ((double)number * rand() / (RAND_MAX + 1.0))); // [1, number]
}
}
/*
* i∈[N-1,0) /从后往前循环N-2遍
* j∈[N-1,N-i-1) //每遍循环要处理的无序部分
* swap(j,j-1) //从倒数第一个元素开始相连两两比较(升序/降序),
* 第一遍会将最大(或者最小)的元素一步一步移到第一个位置上,
* 第二遍会将第二大(或者第二小)的元素一步一步移到第二个位置上
*/
int bubble_sort( int * ary, int len )
{
int i, j;
int temp;
for( i=len-1; i>0; --i ) {
printf("\n\n");
for( j=len-1; j>len-i-1; --j ) {
printf("a[%d] & a[%d](i=%d, j=%d) ", j, j-1, i, j);
if( ary[j] > ary[j-1] ) {
temp = ary[j];
ary[j] = ary[j-1];
ary[j-1] = temp;
printf("swap ");
}
print_ary( ary, len );
}
}
}
int main( int argc, char ** argv )
{
int *pary = NULL;
if (argc !=2)
{
printf("\nUsage: %s Number\n", argv[0]);
return -1;
}
create_rondom_number(&pary, (unsigned int)atoi(argv[1]));
printf("\n\nrandom number: ");
print_ary( pary, (unsigned int)atoi(argv[1]) );
printf("Start sortting: \n");
bubble_sort( pary, (unsigned int)atoi(argv[1]));
printf("\n\nafter sorted: ");
print_ary( pary, (unsigned int)atoi(argv[1]) );
return 0;
}
运行结果:
[root@localhost sort]# ./bubble3 5
random number: 1 1 5 5 5
Start sortting:
a[4] & a[3](i=4, j=4) 1 1 5 5 5
a[3] & a[2](i=4, j=3) 1 1 5 5 5
a[2] & a[1](i=4, j=2) swap 1 5 1 5 5
a[1] & a[0](i=4, j=1) swap 5 1 1 5 5
a[4] & a[3](i=3, j=4) 5 1 1 5 5
a[3] & a[2](i=3, j=3) swap 5 1 5 1 5
a[2] & a[1](i=3, j=2) swap 5 5 1 1 5
a[4] & a[3](i=2, j=4) swap 5 5 1 5 1
a[3] & a[2](i=2, j=3) swap 5 5 5 1 1
a[4] & a[3](i=1, j=4) 5 5 5 1 1
after sorted: 5 5 5 1 1
[root@localhost sort]#
3.
j∈[i+1,N) //每遍循环要处理的无序部分
swap(i,j) //从第一个元素开始与后边所有元素两两比较,接着第二元素与后边所有元素两两比较,以此类推。即将最大(或者最小)的元素放到第一个位置,第二大(或第二小)的元素放到第二位置上,以此类推
源码:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
void print_ary( int * ary, unsigned int len )
{
while( len-- > 0 ) {
printf("%d ", *ary++ );
}
putchar('\n');
}
void create_rondom_number(int **parray, unsigned int number)
{
struct timeval tpstart;
unsigned int i =0;
if (NULL != *parray)
{
return;
}
*parray = (int *)malloc(sizeof(unsigned int) * number);
(void)memset(*parray, 0, sizeof(unsigned int) * number);
gettimeofday(&tpstart,NULL);
//srandom(time(NULL));
srandom(tpstart.tv_usec);
for (i=0; i<number; ++i)
{
//(*parray)[i] = random()%number; // range is [0, number-1]
//(*parray)[i] = random()%(b-a) + a; //range is [a, b)
((*parray)[i] = 1 + (int) ((double)number * rand() / (RAND_MAX + 1.0))); // [1, number]
}
}
/*
* i∈[0,N-1) //从前往后循环N-2遍
* j∈[i+1,N) //每遍循环要处理的无序部分
* swap(i,j) //从第一个元素开始与后边所有元素两两比较,
* 接着第二元素与后边所有元素两两比较,以此类推。
* 即将最大(或者最小)的元素放到第一个位置,第二大(或第二小)的元素放到第二位置上,以此类推
*/
void bubble_sort(int *a, int n)
{
int *p1 = a;
int *p2 = a;
int i;
int j;
int tmp;
for (i = 0; i < n-1; i++)
{
printf("\n\n");
for (j = i+1; j< n; j++)
{
printf("a[%d] & a[%d](i=%d j=%d) ", i, j, i, j);
if (a[i] > a[j])
{
tmp = a[i];
a[i] = a[j];
a[j] = tmp;
printf("swap ");
}
print_ary( a, n );
}
}
}
int main( int argc, char ** argv )
{
int *pary = NULL;
if (argc !=2)
{
printf("\nUsage: %s Number\n", argv[0]);
return -1;
}
create_rondom_number(&pary, (unsigned int)atoi(argv[1]));
printf("\n\nrandom number: ");
print_ary( pary, (unsigned int)atoi(argv[1]) );
printf("Start sortting: \n");
bubble_sort( pary, (unsigned int)atoi(argv[1]));
printf("\n\nafter sorted: ");
print_ary( pary, (unsigned int)atoi(argv[1]) );
return 0;
}
运行结果:
[root@localhost sort]# ./bubble1 5
random number: 1 4 2 4 1
Start sortting:
a[0] & a[1](i=0 j=1) 1 4 2 4 1
a[0] & a[2](i=0 j=2) 1 4 2 4 1
a[0] & a[3](i=0 j=3) 1 4 2 4 1
a[0] & a[4](i=0 j=4) 1 4 2 4 1
a[1] & a[2](i=1 j=2) swap 1 2 4 4 1
a[1] & a[3](i=1 j=3) 1 2 4 4 1
a[1] & a[4](i=1 j=4) swap 1 1 4 4 2
a[2] & a[3](i=2 j=3) 1 1 4 4 2
a[2] & a[4](i=2 j=4) swap 1 1 2 4 4
a[3] & a[4](i=3 j=4) 1 1 2 4 4
after sorted: 1 1 2 4 4
[root@localhost sort]#
4.
i∈[N-1,0) //从后往前循环N-2遍
swap(i,j) //从最后一个元素开始与前边所有元素两两比较,接着倒数第二元素与前边所有元素两两比较,以此类推。即将最大(或者最小)的元素放到第最后一个位置,第二大(或第二小)的元素放到倒数第二个位置上,以此类推
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
void print_ary( int * ary, unsigned int len )
{
while( len-- > 0 ) {
printf("%d ", *ary++ );
}
putchar('\n');
}
void create_rondom_number(int **parray, unsigned int number)
{
//struct timeval tpstart;//for linux
unsigned int i =0;
if (NULL != *parray)
{
return;
}
*parray = (int *)malloc(sizeof(unsigned int) * number);
(void)memset(*parray, 0, sizeof(unsigned int) * number);
//gettimeofday(&tpstart,NULL); //for linux
srand(time(NULL));//standard c
//srandom(time(NULL));//for linux
//srandom(tpstart.tv_usec);//for linux
for (i=0; i<number; ++i)
{
(*parray)[i] = rand()%number; // range is [0, number-1] //standard c
//(*parray)[i] = random()%number; // range is [0, number-1]//for linux
//(*parray)[i] = random()%(b-a) + a; //range is [a, b)//for linux
//((*parray)[i] = 1 + (int) ((double)number * rand() / (RAND_MAX + 1.0))); // [1, number]//for linux
}
}
/*
i∈[N-1,0) //从后往前循环N-2遍
j∈(i-1,0] //每遍循环要处理的无序部分
swap(i,j) //从最后一个元素开始与前边所有元素两两比较,
接着倒数第二元素与前边所有元素两两比较,以此类推。
即将最大(或者最小)的元素放到第最后一个位置,
第二大(或第二小)的元素放到倒数第二个位置上,以此类推
*/
void bubble_sort(int *a, int n)
{
int i;
int j;
int tmp;
for (i=n-1; i > 0; --i)
{
printf("\n\n");
for (j=i-1; j>=0; --j)
{
printf("a[%d] & a[%d](i=%d j=%d) ", i, j, i, j);
if (a[i] > a[j])
{
tmp = a[i];
a[i] = a[j];
a[j] = tmp;
printf("swap ");
}
print_ary( a, n );
}
}
}
int main( int argc, char ** argv )
{
int *pary = NULL;
if (argc !=2)
{
printf("\nUsage: %s Number\n", argv[0]);
return -1;
}
create_rondom_number(&pary, (unsigned int)atoi(argv[1]));
printf("\n\nrandom number: ");
print_ary( pary, (unsigned int)atoi(argv[1]) );
printf("Start sortting: \n");
bubble_sort( pary, (unsigned int)atoi(argv[1]));
printf("\n\nafter sorted: ");
print_ary( pary, (unsigned int)atoi(argv[1]) );
return 0;
}
运行结果:
random number: 0 1 2 3 0
Start sortting:
a[4] & a[3](i=4 j=3) 0 1 2 3 0
a[4] & a[2](i=4 j=2) 0 1 2 3 0
a[4] & a[1](i=4 j=1) 0 1 2 3 0
a[4] & a[0](i=4 j=0) 0 1 2 3 0
a[3] & a[2](i=3 j=2) swap 0 1 3 2 0
a[3] & a[1](i=3 j=1) swap 0 2 3 1 0
a[3] & a[0](i=3 j=0) swap 1 2 3 0 0
a[2] & a[1](i=2 j=1) swap 1 3 2 0 0
a[2] & a[0](i=2 j=0) swap 2 3 1 0 0
a[1] & a[0](i=1 j=0) swap 3 2 1 0 0
after sorted: 3 2 1 0 0
5.
改进源码:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
void print_ary( int * ary, unsigned int len )
{
while( len-- > 0 ) {
printf("%d ", *ary++ );
}
putchar('\n');
}
void create_rondom_number(int **parray, unsigned int number)
{
struct timeval tpstart;
unsigned int i =0;
if (NULL != *parray)
{
return;
}
*parray = (int *)malloc(sizeof(unsigned int) * number);
(void)memset(*parray, 0, sizeof(unsigned int) * number);
gettimeofday(&tpstart,NULL);
//srandom(time(NULL));
srandom(tpstart.tv_usec);
for (i=0; i<number; ++i)
{
//(*parray)[i] = random()%number; // range is [0, number-1]
//(*parray)[i] = random()%(b-a) + a; //range is [a, b)
((*parray)[i] = 1 + (int) ((double)number * rand() / (RAND_MAX + 1.0))); // [1, number]
}
}
/*
*改进的冒泡排序,原理就是进行一趟从头到尾的比较,
*都没有发生交换的行为(使用一个标志来记录此行为),这表示此排序已经完成了,可以省略后边的比较了
*/
void bubble_sort(int array[],int n)
{
int i,j,flag,temp, counter=0;
for(i = 0; i < n-1; i++)
{
flag = 1;
printf("\n\n");
for(j = 0; j < n-i-1; j++)
{
counter++;
printf("a[%d] & a[%d](i=%d, j=%d) ", j, j+1, i, j);
if(array[j] > array[j+1])
{
temp= array[j];
array[j] = array[j+1];
array[j+1] = temp;
flag = 0;
printf("swap ");
}
print_ary( array, n );
}
if (1 == flag)
{
printf("--break from %d \n",i); //首先打印出,在第几层循环时顺序已排好
break; //跳出循环
}
}
printf("counter=%d theoretical value=%d \n", counter, (n*(n-1))/2);
return;
}
int main( int argc, char ** argv )
{
int *pary = NULL;
if (argc !=2)
{
printf("\nUsage: %s Number\n", argv[0]);
return -1;
}
create_rondom_number(&pary, (unsigned int)atoi(argv[1]));
printf("\n\nrandom number: ");
print_ary( pary, (unsigned int)atoi(argv[1]) );
printf("Start sortting: \n");
bubble_sort( pary, (unsigned int)atoi(argv[1]));
printf("\n\nafter sorted: ");
print_ary( pary, (unsigned int)atoi(argv[1]) );
return 0;
}
运行结果:
[root@localhost sort]# ./bubble2 5
random number: 4 5 2 4 1
Start sortting:
a[0] & a[1](i=0, j=0) 4 5 2 4 1
a[1] & a[2](i=0, j=1) swap 4 2 5 4 1
a[2] & a[3](i=0, j=2) swap 4 2 4 5 1
a[3] & a[4](i=0, j=3) swap 4 2 4 1 5
a[0] & a[1](i=1, j=0) swap 2 4 4 1 5
a[1] & a[2](i=1, j=1) 2 4 4 1 5
a[2] & a[3](i=1, j=2) swap 2 4 1 4 5
a[0] & a[1](i=2, j=0) 2 4 1 4 5
a[1] & a[2](i=2, j=1) swap 2 1 4 4 5
a[0] & a[1](i=3, j=0) swap 1 2 4 4 5
counter=10 theoretical value=10
after sorted: 1 2 4 4 5
[root@localhost sort]#
http://zh.wikipedia.org/wiki/%E5%86%92%E6%B3%A1%E6%8E%92%E5%BA%8F
http://baike.baidu.com/view/1313793.htm