一、算法原理

冒泡排序是一种常用的排序算法,属于稳定排序法,其时间复杂度为O(n^2)。
冒泡排序法的原理就是从前向后依次比较相邻两个元素的大小,大元素后沉,类似于水中的泡泡逐步上浮的过程,随着泡泡逐渐接近水面,水中压强逐渐减小,水泡体积逐渐增大,因此成为冒泡排序。
冒泡排序法包括多趟排序过程,每一趟排序都是从数组的第一个元素开始,以步长为1的增量依次对相邻的两个元素进行比较大小,反序的话则交换此二元素。

Demo:
假设有数据如下表所示:数组记为data
在这里插入图片描述
第一趟排序:
从下标为1的元素开始,向后依次比较相邻元素大小。首先比较data[1]和data[2],此时data[1] < data[2],因此不用交换元素。
在这里插入图片描述
之后比较data[2]和data[3]的大小,此时数据反序,需要交换
在这里插入图片描述
接着比较data[3]和data[4]的大小,此时数据不需要交换。
在这里插入图片描述
之后比较data[4]和data[5]的大小,此时数据需要交换。至此完成了第一趟冒泡排序过程,把数组中的最大元素冒泡到了最后的位置。
仔细想想,像不像水中的水泡冒泡的过程。
在这里插入图片描述
第二趟排序:
和第一趟排序一样,仍旧从数组的第一个元素开始向后依次进行比较大小。但是由于经过第一趟排序之后,最大的元素已经到了最后的位置,因此第二趟排序就截止到数组的倒数第二个位置。
在这里插入图片描述
第三趟排序:
在这里插入图片描述
第四趟排序:
在这里插入图片描述
至此,该数组的冒泡排序结束。从上述演示过程可以看出,具有n个元素的数组使用冒泡排序法进行排序,需要进行n-1趟排序,每一趟排序都冒出剩余元素中的最大值,放到剩余元素的末尾。

二、冒泡排序算法流程图

在这里插入图片描述

三、冒泡排序算法之C程序

1.冒泡排序算法之C语言版

/*
功能:使用选择排序法对数组data进行排序
输入参数:
	data[],已知数据散乱的数组
	n,元素的个数
输出参数:
	data[],排好序的数组
返回值:无 
*/
void BubbleSort( int data[], int n )
{
	int i, j, k, t;
	for( i = 1; i <= n-1; i++ )
	{
		for( j = 1; j <= n-i; j++ )
		{
			if( data[j+1] < data[j] )
			{
				t         = data[j+1];
				data[j+1] = data[j];
				data[j]   = t;
			}
		}
	}
}

2.完整的代码(仅供参考)

#include"stdio.h"
#define MaxLength 100

int TotalNum = 0;
void InputData( int &count, int arrt[] );
void BubbleSort( int data[], int n );

int main()
{
	int count = 0, i, j;
	int data[MaxLength];
	InputData( count, data );
	printf( "排序前的数据:" );
	for( i = 1; i <= count; i++ )
	{
		printf( "%5d", data[i] );
	}
	printf( "\n" ); 
	BubbleSort( data, count ); 
	
	return 0;
} 
/*
功能:使用选择排序法对数组data进行排序
输入参数:
	data[],已知数据散乱的数组
	n,元素的个数
输出参数:
	data[],排好序的数组
返回值:无 
*/
void BubbleSort( int data[], int n )
{
	int i, j, k, t;
	for( i = 1; i <= n-1; i++ )
	{
		for( j = 1; j <= n-i; j++ )
		{
			if( data[j+1] < data[j] )
			{
				t         = data[j+1];
				data[j+1] = data[j];
				data[j]   = t;
			}
		}
		//输出每一轮排序结果 
		printf( "第 %d 趟排序:", i );
		for( k = 1; k <= n; k++  )
		{
			printf( "%5d", data[k] );
		}
		printf( "\n" );
	}
}

//从键盘读入一组整数存储到数组arr中,元素个数存储到count中 
void InputData( int &count, int arrt[] )
{
	int i = 0, data;
	while( 1 )
	{
		printf( "input an integer(end of 65535)" );
		scanf( "%d", &data );
		if( data == 65535 )
		{
			break;
		}
		else
		{
			arrt[++i] = data;
		}
	}
	count = i;
}

3.测试用例
测试用例一
在这里插入图片描述
测试用例二
在这里插入图片描述

四、算法改进

上述算法,从第二个测试用例可以发现,经过第一趟排序之后,数据就已经处于排好序的状态了,因此不需要再进行后续的排序。为了解决此问题,提高算法的效率,可以对上述算法进行改进。改进的方法之一是引入提前结束排序标志flag,进行每一趟排序前将其值置为1,表示可以提前结束,之后进行相邻的两个元素比较大小时,如果需要交换数据,则将flag的值置为0,表示不能提前结束。这样当进行某一趟排序时,如果不需要交换数据的操作,则表示数据已经处于排好序的状态了,此时就可以提前结束排序。

具体算法实现如下:

void BubbleSort_V1( int data[], int n )
{
	int i, j, k, t;
	bool flag;//提前结束排序的标志,1表示提前结束 
	for( i = 1; i <= n-1; i++ )
	{
		flag = 1;
		for( j = 1; j <= n-i; j++ )
		{
			if( data[j+1] < data[j] )
			{
				flag = 0; 
				t         = data[j+1];
				data[j+1] = data[j];
				data[j]   = t;
			}
		}
		//输出每一轮排序结果 
		printf( "第 %d 趟排序:", i );
		for( k = 1; k <= n; k++  )
		{
			printf( "%5d", data[k] );
		}
		printf( "\n" );
		
		if( flag == 1 )
		{
			break;
		}
	}
}

测试用例:

在这里插入图片描述
从测试用例可以发现,对于数组{11,15,8,19,2},元素个数n=5,需要进行n-1=4趟排序得到最终的排序结果。对于数组{5,2,9,8,10},元素个数n=5,只需要进行一趟排序就可以得到最终的排序结果。而改进的冒泡排序算法可以通过一趟排序即可以达成结果,因此其效率得到了提高。

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐