经典排序之冒泡排序及其最终优化

冒泡排序(Bubble Sort):相邻的两个元素进行大小比较,如果前一个比后一个大,则二者发生交换。

第一趟:8和6比,8比6大,二者交换,6 8 4 12 1 ,8和4比,8比4大,二者交换,6 4 8 12 1,8和12比,8比12小,不交换,6 4 8 12 1,12和1比,12比1大,二者交换,6 4 8 1 12。
第二趟:6和4比,6比4大,二者交换,4 6 8 1 12,6和8比,6比8小,不交换,8和1比,8比1大,二者交换,4 6 1 8 12,8和最后一个不用比了,因为第一趟比较已经把最大的移到了最后面,同理这一趟也把第二大的移到了倒数第二个位置。

第三趟:4和6比,4 比6小,不交换,6和1比,6比1大,二者交换,4 1 6 8 12。
第四趟:4和1比,4比1大,二者交换,1 4 6 8 12,结束。
在这里插入图片描述

n个元素需要n-1趟操作完成排序,每一趟相邻两个元素比较,这是一个典型的循环嵌套过程,也是冒泡排序的最基础版本。

void BubbleSort(int arr[],int nlength)
{
    
    
	if(arr == NULL||nlength<=0) return;
	
	int i;
	int j;
	for(i=0;i<nlength-1;i++)
	{
    
    
		for(j=0;j<nlength-1-i;j++) //每经过i趟,后数的i个元素的位置就会被放好,就少比较i次
		{
    
    
			if(arr[j]>arr[j+1])
			{
    
    
				arr[j] = arr[j]^arr[j+1];
				arr[j+1] = arr[j]^arr[j+1];
				arr[j] = arr[j]^arr[j+1];
			}
		}
	}	
}

看完了基础版本让我们接着分析,我们在得到一组数据以前,是不知道他是否有序的,如果给我们一组有序的数据我们是不需要进行排序的,如果我遍历一遍,发现数据有序,就不需要排序了。那我们怎么遍历一遍就知道数据有序呢?如果每一个后面的数据都大于他前面的数据,那么是不会进入到代码中交换那一步的,我们需要一个标记记录是否进入到交换中,如果进入则改变标记状态,如果遍历一遍以后,标记状态没有改变,则数据有序,无需进行排序。

void BubbleSort(int arr[],int nlength)
{
    
    
	if(arr == NULL||nlength<=0) return;

	int flag ;
	int i;
	int j;
	for(i=0;i<nlength-1;i++)
	{
    
    
		flag = 0;
		for(j=0;j<nlength-1-i;j++)
		{
    
    
			if(arr[j]>arr[j+1])
			{
    
    
				arr[j] = arr[j]^arr[j+1];
				arr[j+1] = arr[j]^arr[j+1];
				arr[j] = arr[j]^arr[j+1];
				flag=1;
			}
		}
		if(flag == 0) break;	
	}	
}

然后让我们再来看,假如现在有一组数据是12,8,1,9,3,14,15,19,20。
经过第一趟排序以后的结果是8,1,9,3,12,14,15,19,20。这组数据刚一看可能觉得很乱,但是我们第一趟走完以后发现12这个数字的位置很特殊,12是上一次遍历的最后的交换位置,意味着他后面都没有发生交换,他后面都是排好序的且放好的,所以我们下一次操作的元素就到它前面就可以了。

假如说12的位置为F,那么12前面还剩下F个元素,还需要走F-1趟,最外面的循环是控制趟数的,一共需要n-1趟,n-1-i是剩余趟数,则,n-1-i=F-1;i=n-F;

void BubbleSort(int arr[],int nlength)
{
    
    
	if(arr == NULL||nlength<=0) return;

	int flag ;
	int i;
	int j;
	for(i=0;i<nlength-1;i++)
	{
    
    
		flag = 0;
		for(j=0;j<nlength-1-i;j++)
		{
    
    
			if(arr[j]>arr[j+1])
			{
    
    
				arr[j] = arr[j]^arr[j+1];
				arr[j+1] = arr[j]^arr[j+1];
				arr[j] = arr[j]^arr[j+1];
				flag=j+1;  //记录位置(相当于12的位置)
			}
		}
		if(flag == 0) break;
		i=nlength-flag-1; (因为还要i++,所以减去一个1}	
}

猜你喜欢

转载自blog.csdn.net/scarificed/article/details/113095207
今日推荐