首页 > 代码库 > 排序——冒泡排序(三种方法)

排序——冒泡排序(三种方法)

冒泡排序的基本思想:

        在要排序的一组数中,对当前还未排好序的范围内的全部数,自上而下对相邻的两个数依次进行比较和调整,让较大的数往下沉,较小的往上冒。即:每当两相邻的数比较后发现它们的排序与排序要求相反时,就将它们互换。

关于程序中4中冒泡排序写法的说明:

bubble_sort1:基本的冒泡排序的写法。

bubble_sort2:基本冒泡排序的不同写法,基本的冒泡排序是每次遍历,每次缩小范围1,这种办法是每次正向和反向遍历,每次缩小范围2,所以两者的比较次数也是一样的。

bubble_sort3:如果在某一趟的冒泡途中没有出现数据交换,那就只能是数据已经被排好序了,这样就可以提前得知数据排好序从而中断循环,消除掉不必要的比较。

bubble_sort4:如果在某一趟的冒泡途中最后的交换出现在pos的位置,那么表示pos位置以后都已经排好序,这样相比于基本冒泡每一次缩小遍历范围1而言有可能一次缩小的遍历范围>=1,所以这样也可以提高排序的效率。

程序代码如下:

#include <stdio.h>

int bubble_sort1(int num[], int n) /*最基本的冒泡排序法*/
{
	int i, j, tmp;
	int count = 0;

	for(i = 0; i < n-1; i++) /*冒泡一次放好一个数,冒泡n-1次就可以全部放置好*/
		for(j = 0; j < n-1-i; j++, count++) /*后面的i个数已经为有序序列*/
		{
			if(num[j] > num[j+1])
			{
				tmp = num[j];
				num[j] = num[j+1];
				num[j+1] = tmp;
			}
		}

	return count;
}

int bubble_sort2( int num[], int n) /*基本冒泡法的另一种写法*/
{  
    int low = 0;   
    int high= n -1; /*设置边界low和high*/  
    int tmp, j, count = 0; 
    while (low < high) 
	{  
        for(j=low; j < high; j++, count++) /*正向冒泡,找最大值*/  
            if (num[j] > num[j+1]) 
			{  
                tmp = num[j]; 
				num[j] = num[j+1];
				num[j+1] = tmp;  
            }   
        high --; /*更新冒泡区间*/
        for(j=high; j > low; j--, count++) /*反向冒泡,找最小值*/   
            if (num[j] < num[j-1]) 
			{  
                tmp = num[j]; 
				num[j] = num[j-1];
				num[j-1] = tmp;  
            }  
        low ++; /*更新冒泡区间*/
    }  
	
	return count;
}  

int bubble_sort3(int num[], int n) /*加入一标志性变量exchange,用于标志某一趟排序过程中是否有数据交换,
                                     如果进行某一趟排序时并没有进行数据交换,则说明数据已经按要求排列好,
									 则立即结束排序,避免不必要的比较过程。*/
{
	int i, j, tmp, exchange = 1, count =0;

	for(i = 0; i<n-1 && (exchange==1); i++) /*判断上一趟是否有数据交换,没有则表明排序已完成*/
		for(j = 0, exchange=0; j < n-1-i; j++, count++)
		{
			if(num[j] > num[j+1])
			{
				exchange = 1;
				tmp = num[j];
				num[j] = num[j+1];
				num[j+1] = tmp;
			}
		}

	return count;
}

int bubble_sort4(int num[], int n) /*加入一标志性变量pos,用于标志某一趟排序过程中最后交换数据的位置,
                                     那么在这个位置之后的数据都是已经排好序的,进而根据这个pos重新计算
									 还剩余的冒泡次数*/
{
	int i, j, tmp, pos, count =0;

	for(i=0; i < n-1; i=n-pos) /*n-pos表示已经排好序的个数,用来替代以前的i++方式计算已经排好序的个数*/
		for(j=0, pos=0; j < n-1-i; j++, count++) /*pos=0是必须的,不然没有交换的时候会出现死循环*/
		{
			if(num[j] > num[j+1])
			{
				tmp = num[j];
				num[j] = num[j+1];
				num[j+1] = tmp;
				pos = j+1; /*从j+1开始的往后的数据已经排好序*/
			}
		}

	return count;
}
 

void print_num(int num[], int n)
{
	int i;

	printf("[0-%d]: ", n-1);
	for(i=0; i < n; i++)
		printf("%d ", num[i]);
	printf("\n");
}

int main()
{
	int num1[] = {1, 9, 3, 5, 6, 2, 7, 10, 8, 4, 11, 15, 13, 12, 16, 14};
	int num2[] = {1, 9, 3, 5, 6, 2, 7, 10, 8, 4, 11, 15, 13, 12, 16, 14};
	int num3[] = {1, 9, 3, 5, 6, 2, 7, 10, 8, 4, 11, 15, 13, 12, 16, 14};
	int num4[] = {1, 9, 3, 5, 6, 2, 7, 10, 8, 4, 11, 15, 13, 12, 16, 14};
	int cmp_cnt;

	cmp_cnt = bubble_sort1(num1, sizeof(num1)/sizeof(int));
	print_num(num1, sizeof(num1)/sizeof(int));
	printf("Method1 compare count is: %d.\n\n", cmp_cnt);

	cmp_cnt = bubble_sort2(num2, sizeof(num2)/sizeof(int));
	print_num(num2, sizeof(num2)/sizeof(int));
	printf("Method2 compare count is: %d.\n\n", cmp_cnt);

	cmp_cnt = bubble_sort3(num3, sizeof(num3)/sizeof(int));
	print_num(num3, sizeof(num3)/sizeof(int));
	printf("Method3 compare count is: %d.\n\n", cmp_cnt);

	cmp_cnt = bubble_sort4(num4, sizeof(num4)/sizeof(int));
	print_num(num4, sizeof(num4)/sizeof(int));
	printf("Method4 compare count is: %d.\n\n", cmp_cnt);

	return 0;
}
程序运行结果截图: